1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * maxim_thermocouple.c - Support for Maxim thermocouple chips
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016-2018 Matt Ranostay
6*4882a593Smuzhiyun * Author: <matt.ranostay@konsulko.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/mutex.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/of.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/spi/spi.h>
16*4882a593Smuzhiyun #include <linux/iio/iio.h>
17*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
18*4882a593Smuzhiyun #include <linux/iio/trigger.h>
19*4882a593Smuzhiyun #include <linux/iio/buffer.h>
20*4882a593Smuzhiyun #include <linux/iio/triggered_buffer.h>
21*4882a593Smuzhiyun #include <linux/iio/trigger_consumer.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define MAXIM_THERMOCOUPLE_DRV_NAME "maxim_thermocouple"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun enum {
26*4882a593Smuzhiyun MAX6675,
27*4882a593Smuzhiyun MAX31855,
28*4882a593Smuzhiyun MAX31855K,
29*4882a593Smuzhiyun MAX31855J,
30*4882a593Smuzhiyun MAX31855N,
31*4882a593Smuzhiyun MAX31855S,
32*4882a593Smuzhiyun MAX31855T,
33*4882a593Smuzhiyun MAX31855E,
34*4882a593Smuzhiyun MAX31855R,
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static const char maxim_tc_types[] = {
38*4882a593Smuzhiyun 'K', '?', 'K', 'J', 'N', 'S', 'T', 'E', 'R'
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static const struct iio_chan_spec max6675_channels[] = {
42*4882a593Smuzhiyun { /* thermocouple temperature */
43*4882a593Smuzhiyun .type = IIO_TEMP,
44*4882a593Smuzhiyun .info_mask_separate =
45*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
46*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE),
47*4882a593Smuzhiyun .scan_index = 0,
48*4882a593Smuzhiyun .scan_type = {
49*4882a593Smuzhiyun .sign = 's',
50*4882a593Smuzhiyun .realbits = 13,
51*4882a593Smuzhiyun .storagebits = 16,
52*4882a593Smuzhiyun .shift = 3,
53*4882a593Smuzhiyun .endianness = IIO_BE,
54*4882a593Smuzhiyun },
55*4882a593Smuzhiyun },
56*4882a593Smuzhiyun IIO_CHAN_SOFT_TIMESTAMP(1),
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun static const struct iio_chan_spec max31855_channels[] = {
60*4882a593Smuzhiyun { /* thermocouple temperature */
61*4882a593Smuzhiyun .type = IIO_TEMP,
62*4882a593Smuzhiyun .address = 2,
63*4882a593Smuzhiyun .info_mask_separate =
64*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
65*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE),
66*4882a593Smuzhiyun .scan_index = 0,
67*4882a593Smuzhiyun .scan_type = {
68*4882a593Smuzhiyun .sign = 's',
69*4882a593Smuzhiyun .realbits = 14,
70*4882a593Smuzhiyun .storagebits = 16,
71*4882a593Smuzhiyun .shift = 2,
72*4882a593Smuzhiyun .endianness = IIO_BE,
73*4882a593Smuzhiyun },
74*4882a593Smuzhiyun },
75*4882a593Smuzhiyun { /* cold junction temperature */
76*4882a593Smuzhiyun .type = IIO_TEMP,
77*4882a593Smuzhiyun .address = 0,
78*4882a593Smuzhiyun .channel2 = IIO_MOD_TEMP_AMBIENT,
79*4882a593Smuzhiyun .modified = 1,
80*4882a593Smuzhiyun .info_mask_separate =
81*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
82*4882a593Smuzhiyun .scan_index = 1,
83*4882a593Smuzhiyun .scan_type = {
84*4882a593Smuzhiyun .sign = 's',
85*4882a593Smuzhiyun .realbits = 12,
86*4882a593Smuzhiyun .storagebits = 16,
87*4882a593Smuzhiyun .shift = 4,
88*4882a593Smuzhiyun .endianness = IIO_BE,
89*4882a593Smuzhiyun },
90*4882a593Smuzhiyun },
91*4882a593Smuzhiyun IIO_CHAN_SOFT_TIMESTAMP(2),
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun static const unsigned long max31855_scan_masks[] = {0x3, 0};
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun struct maxim_thermocouple_chip {
97*4882a593Smuzhiyun const struct iio_chan_spec *channels;
98*4882a593Smuzhiyun const unsigned long *scan_masks;
99*4882a593Smuzhiyun u8 num_channels;
100*4882a593Smuzhiyun u8 read_size;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* bit-check for valid input */
103*4882a593Smuzhiyun u32 status_bit;
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
107*4882a593Smuzhiyun [MAX6675] = {
108*4882a593Smuzhiyun .channels = max6675_channels,
109*4882a593Smuzhiyun .num_channels = ARRAY_SIZE(max6675_channels),
110*4882a593Smuzhiyun .read_size = 2,
111*4882a593Smuzhiyun .status_bit = BIT(2),
112*4882a593Smuzhiyun },
113*4882a593Smuzhiyun [MAX31855] = {
114*4882a593Smuzhiyun .channels = max31855_channels,
115*4882a593Smuzhiyun .num_channels = ARRAY_SIZE(max31855_channels),
116*4882a593Smuzhiyun .read_size = 4,
117*4882a593Smuzhiyun .scan_masks = max31855_scan_masks,
118*4882a593Smuzhiyun .status_bit = BIT(16),
119*4882a593Smuzhiyun },
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun struct maxim_thermocouple_data {
123*4882a593Smuzhiyun struct spi_device *spi;
124*4882a593Smuzhiyun const struct maxim_thermocouple_chip *chip;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun u8 buffer[16] ____cacheline_aligned;
127*4882a593Smuzhiyun char tc_type;
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun
maxim_thermocouple_read(struct maxim_thermocouple_data * data,struct iio_chan_spec const * chan,int * val)130*4882a593Smuzhiyun static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
131*4882a593Smuzhiyun struct iio_chan_spec const *chan, int *val)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun unsigned int storage_bytes = data->chip->read_size;
134*4882a593Smuzhiyun unsigned int shift = chan->scan_type.shift + (chan->address * 8);
135*4882a593Smuzhiyun __be16 buf16;
136*4882a593Smuzhiyun __be32 buf32;
137*4882a593Smuzhiyun int ret;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun switch (storage_bytes) {
140*4882a593Smuzhiyun case 2:
141*4882a593Smuzhiyun ret = spi_read(data->spi, (void *)&buf16, storage_bytes);
142*4882a593Smuzhiyun *val = be16_to_cpu(buf16);
143*4882a593Smuzhiyun break;
144*4882a593Smuzhiyun case 4:
145*4882a593Smuzhiyun ret = spi_read(data->spi, (void *)&buf32, storage_bytes);
146*4882a593Smuzhiyun *val = be32_to_cpu(buf32);
147*4882a593Smuzhiyun break;
148*4882a593Smuzhiyun default:
149*4882a593Smuzhiyun ret = -EINVAL;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (ret)
153*4882a593Smuzhiyun return ret;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* check to be sure this is a valid reading */
156*4882a593Smuzhiyun if (*val & data->chip->status_bit)
157*4882a593Smuzhiyun return -EINVAL;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun *val = sign_extend32(*val >> shift, chan->scan_type.realbits - 1);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
maxim_thermocouple_trigger_handler(int irq,void * private)164*4882a593Smuzhiyun static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun struct iio_poll_func *pf = private;
167*4882a593Smuzhiyun struct iio_dev *indio_dev = pf->indio_dev;
168*4882a593Smuzhiyun struct maxim_thermocouple_data *data = iio_priv(indio_dev);
169*4882a593Smuzhiyun int ret;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun ret = spi_read(data->spi, data->buffer, data->chip->read_size);
172*4882a593Smuzhiyun if (!ret) {
173*4882a593Smuzhiyun iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
174*4882a593Smuzhiyun iio_get_time_ns(indio_dev));
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun iio_trigger_notify_done(indio_dev->trig);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun return IRQ_HANDLED;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
maxim_thermocouple_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)182*4882a593Smuzhiyun static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev,
183*4882a593Smuzhiyun struct iio_chan_spec const *chan,
184*4882a593Smuzhiyun int *val, int *val2, long mask)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun struct maxim_thermocouple_data *data = iio_priv(indio_dev);
187*4882a593Smuzhiyun int ret = -EINVAL;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun switch (mask) {
190*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
191*4882a593Smuzhiyun ret = iio_device_claim_direct_mode(indio_dev);
192*4882a593Smuzhiyun if (ret)
193*4882a593Smuzhiyun return ret;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun ret = maxim_thermocouple_read(data, chan, val);
196*4882a593Smuzhiyun iio_device_release_direct_mode(indio_dev);
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (!ret)
199*4882a593Smuzhiyun return IIO_VAL_INT;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun break;
202*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
203*4882a593Smuzhiyun switch (chan->channel2) {
204*4882a593Smuzhiyun case IIO_MOD_TEMP_AMBIENT:
205*4882a593Smuzhiyun *val = 62;
206*4882a593Smuzhiyun *val2 = 500000; /* 1000 * 0.0625 */
207*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
208*4882a593Smuzhiyun break;
209*4882a593Smuzhiyun default:
210*4882a593Smuzhiyun *val = 250; /* 1000 * 0.25 */
211*4882a593Smuzhiyun ret = IIO_VAL_INT;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun break;
214*4882a593Smuzhiyun case IIO_CHAN_INFO_THERMOCOUPLE_TYPE:
215*4882a593Smuzhiyun *val = data->tc_type;
216*4882a593Smuzhiyun ret = IIO_VAL_CHAR;
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun return ret;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun static const struct iio_info maxim_thermocouple_info = {
224*4882a593Smuzhiyun .read_raw = maxim_thermocouple_read_raw,
225*4882a593Smuzhiyun };
226*4882a593Smuzhiyun
maxim_thermocouple_probe(struct spi_device * spi)227*4882a593Smuzhiyun static int maxim_thermocouple_probe(struct spi_device *spi)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun const struct spi_device_id *id = spi_get_device_id(spi);
230*4882a593Smuzhiyun struct iio_dev *indio_dev;
231*4882a593Smuzhiyun struct maxim_thermocouple_data *data;
232*4882a593Smuzhiyun const int chip_type = (id->driver_data == MAX6675) ? MAX6675 : MAX31855;
233*4882a593Smuzhiyun const struct maxim_thermocouple_chip *chip =
234*4882a593Smuzhiyun &maxim_thermocouple_chips[chip_type];
235*4882a593Smuzhiyun int ret;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
238*4882a593Smuzhiyun if (!indio_dev)
239*4882a593Smuzhiyun return -ENOMEM;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun indio_dev->info = &maxim_thermocouple_info;
242*4882a593Smuzhiyun indio_dev->name = MAXIM_THERMOCOUPLE_DRV_NAME;
243*4882a593Smuzhiyun indio_dev->channels = chip->channels;
244*4882a593Smuzhiyun indio_dev->available_scan_masks = chip->scan_masks;
245*4882a593Smuzhiyun indio_dev->num_channels = chip->num_channels;
246*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun data = iio_priv(indio_dev);
249*4882a593Smuzhiyun data->spi = spi;
250*4882a593Smuzhiyun data->chip = chip;
251*4882a593Smuzhiyun data->tc_type = maxim_tc_types[id->driver_data];
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun ret = devm_iio_triggered_buffer_setup(&spi->dev,
254*4882a593Smuzhiyun indio_dev, NULL,
255*4882a593Smuzhiyun maxim_thermocouple_trigger_handler, NULL);
256*4882a593Smuzhiyun if (ret)
257*4882a593Smuzhiyun return ret;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (id->driver_data == MAX31855)
260*4882a593Smuzhiyun dev_warn(&spi->dev, "generic max31855 ID is deprecated\nplease use more specific part type");
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun return devm_iio_device_register(&spi->dev, indio_dev);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun static const struct spi_device_id maxim_thermocouple_id[] = {
266*4882a593Smuzhiyun {"max6675", MAX6675},
267*4882a593Smuzhiyun {"max31855", MAX31855},
268*4882a593Smuzhiyun {"max31855k", MAX31855K},
269*4882a593Smuzhiyun {"max31855j", MAX31855J},
270*4882a593Smuzhiyun {"max31855n", MAX31855N},
271*4882a593Smuzhiyun {"max31855s", MAX31855S},
272*4882a593Smuzhiyun {"max31855t", MAX31855T},
273*4882a593Smuzhiyun {"max31855e", MAX31855E},
274*4882a593Smuzhiyun {"max31855r", MAX31855R},
275*4882a593Smuzhiyun {},
276*4882a593Smuzhiyun };
277*4882a593Smuzhiyun MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun static const struct of_device_id maxim_thermocouple_of_match[] = {
280*4882a593Smuzhiyun { .compatible = "maxim,max6675" },
281*4882a593Smuzhiyun { .compatible = "maxim,max31855" },
282*4882a593Smuzhiyun { .compatible = "maxim,max31855k" },
283*4882a593Smuzhiyun { .compatible = "maxim,max31855j" },
284*4882a593Smuzhiyun { .compatible = "maxim,max31855n" },
285*4882a593Smuzhiyun { .compatible = "maxim,max31855s" },
286*4882a593Smuzhiyun { .compatible = "maxim,max31855t" },
287*4882a593Smuzhiyun { .compatible = "maxim,max31855e" },
288*4882a593Smuzhiyun { .compatible = "maxim,max31855r" },
289*4882a593Smuzhiyun { },
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, maxim_thermocouple_of_match);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun static struct spi_driver maxim_thermocouple_driver = {
294*4882a593Smuzhiyun .driver = {
295*4882a593Smuzhiyun .name = MAXIM_THERMOCOUPLE_DRV_NAME,
296*4882a593Smuzhiyun .of_match_table = maxim_thermocouple_of_match,
297*4882a593Smuzhiyun },
298*4882a593Smuzhiyun .probe = maxim_thermocouple_probe,
299*4882a593Smuzhiyun .id_table = maxim_thermocouple_id,
300*4882a593Smuzhiyun };
301*4882a593Smuzhiyun module_spi_driver(maxim_thermocouple_driver);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
304*4882a593Smuzhiyun MODULE_DESCRIPTION("Maxim thermocouple sensors");
305*4882a593Smuzhiyun MODULE_LICENSE("GPL");
306