xref: /openbmc/linux/drivers/iio/temperature/maxim_thermocouple.c (revision e983940270f10fe8551baf0098be76ea478294a3)
1 /*
2  * maxim_thermocouple.c  - Support for Maxim thermocouple chips
3  *
4  * Copyright (C) 2016 Matt Ranostay <mranostay@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/mutex.h>
20 #include <linux/err.h>
21 #include <linux/spi/spi.h>
22 #include <linux/iio/iio.h>
23 #include <linux/iio/trigger.h>
24 #include <linux/iio/buffer.h>
25 #include <linux/iio/triggered_buffer.h>
26 #include <linux/iio/trigger_consumer.h>
27 
28 #define MAXIM_THERMOCOUPLE_DRV_NAME	"maxim_thermocouple"
29 
30 enum {
31 	MAX6675,
32 	MAX31855,
33 };
34 
35 static const struct iio_chan_spec max6675_channels[] = {
36 	{	/* thermocouple temperature */
37 		.type = IIO_TEMP,
38 		.info_mask_separate =
39 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
40 		.scan_index = 0,
41 		.scan_type = {
42 			.sign = 's',
43 			.realbits = 13,
44 			.storagebits = 16,
45 			.shift = 3,
46 			.endianness = IIO_BE,
47 		},
48 	},
49 	IIO_CHAN_SOFT_TIMESTAMP(1),
50 };
51 
52 static const struct iio_chan_spec max31855_channels[] = {
53 	{	/* thermocouple temperature */
54 		.type = IIO_TEMP,
55 		.address = 2,
56 		.info_mask_separate =
57 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
58 		.scan_index = 0,
59 		.scan_type = {
60 			.sign = 's',
61 			.realbits = 14,
62 			.storagebits = 16,
63 			.shift = 2,
64 			.endianness = IIO_BE,
65 		},
66 	},
67 	{	/* cold junction temperature */
68 		.type = IIO_TEMP,
69 		.address = 0,
70 		.channel2 = IIO_MOD_TEMP_AMBIENT,
71 		.modified = 1,
72 		.info_mask_separate =
73 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
74 		.scan_index = 1,
75 		.scan_type = {
76 			.sign = 's',
77 			.realbits = 12,
78 			.storagebits = 16,
79 			.shift = 4,
80 			.endianness = IIO_BE,
81 		},
82 	},
83 	IIO_CHAN_SOFT_TIMESTAMP(2),
84 };
85 
86 static const unsigned long max31855_scan_masks[] = {0x3, 0};
87 
88 struct maxim_thermocouple_chip {
89 	const struct iio_chan_spec *channels;
90 	const unsigned long *scan_masks;
91 	u8 num_channels;
92 	u8 read_size;
93 
94 	/* bit-check for valid input */
95 	u32 status_bit;
96 };
97 
98 static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
99 	[MAX6675] = {
100 			.channels = max6675_channels,
101 			.num_channels = ARRAY_SIZE(max6675_channels),
102 			.read_size = 2,
103 			.status_bit = BIT(2),
104 		},
105 	[MAX31855] = {
106 			.channels = max31855_channels,
107 			.num_channels = ARRAY_SIZE(max31855_channels),
108 			.read_size = 4,
109 			.scan_masks = max31855_scan_masks,
110 			.status_bit = BIT(16),
111 		},
112 };
113 
114 struct maxim_thermocouple_data {
115 	struct spi_device *spi;
116 	const struct maxim_thermocouple_chip *chip;
117 
118 	u8 buffer[16] ____cacheline_aligned;
119 };
120 
121 static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
122 				   struct iio_chan_spec const *chan, int *val)
123 {
124 	unsigned int storage_bytes = data->chip->read_size;
125 	unsigned int shift = chan->scan_type.shift + (chan->address * 8);
126 	unsigned int buf;
127 	int ret;
128 
129 	ret = spi_read(data->spi, (void *) &buf, storage_bytes);
130 	if (ret)
131 		return ret;
132 
133 	switch (storage_bytes) {
134 	case 2:
135 		*val = be16_to_cpu(buf);
136 		break;
137 	case 4:
138 		*val = be32_to_cpu(buf);
139 		break;
140 	}
141 
142 	/* check to be sure this is a valid reading */
143 	if (*val & data->chip->status_bit)
144 		return -EINVAL;
145 
146 	*val = sign_extend32(*val >> shift, chan->scan_type.realbits - 1);
147 
148 	return 0;
149 }
150 
151 static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private)
152 {
153 	struct iio_poll_func *pf = private;
154 	struct iio_dev *indio_dev = pf->indio_dev;
155 	struct maxim_thermocouple_data *data = iio_priv(indio_dev);
156 	int ret;
157 
158 	ret = spi_read(data->spi, data->buffer, data->chip->read_size);
159 	if (!ret) {
160 		iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
161 						   iio_get_time_ns(indio_dev));
162 	}
163 
164 	iio_trigger_notify_done(indio_dev->trig);
165 
166 	return IRQ_HANDLED;
167 }
168 
169 static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev,
170 				       struct iio_chan_spec const *chan,
171 				       int *val, int *val2, long mask)
172 {
173 	struct maxim_thermocouple_data *data = iio_priv(indio_dev);
174 	int ret = -EINVAL;
175 
176 	switch (mask) {
177 	case IIO_CHAN_INFO_RAW:
178 		ret = iio_device_claim_direct_mode(indio_dev);
179 		if (ret)
180 			return ret;
181 
182 		ret = maxim_thermocouple_read(data, chan, val);
183 		iio_device_release_direct_mode(indio_dev);
184 
185 		if (!ret)
186 			return IIO_VAL_INT;
187 
188 		break;
189 	case IIO_CHAN_INFO_SCALE:
190 		switch (chan->channel2) {
191 		case IIO_MOD_TEMP_AMBIENT:
192 			*val = 62;
193 			*val2 = 500000; /* 1000 * 0.0625 */
194 			ret = IIO_VAL_INT_PLUS_MICRO;
195 			break;
196 		default:
197 			*val = 250; /* 1000 * 0.25 */
198 			ret = IIO_VAL_INT;
199 		};
200 		break;
201 	}
202 
203 	return ret;
204 }
205 
206 static const struct iio_info maxim_thermocouple_info = {
207 	.driver_module = THIS_MODULE,
208 	.read_raw = maxim_thermocouple_read_raw,
209 };
210 
211 static int maxim_thermocouple_probe(struct spi_device *spi)
212 {
213 	const struct spi_device_id *id = spi_get_device_id(spi);
214 	struct iio_dev *indio_dev;
215 	struct maxim_thermocouple_data *data;
216 	const struct maxim_thermocouple_chip *chip =
217 			&maxim_thermocouple_chips[id->driver_data];
218 	int ret;
219 
220 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
221 	if (!indio_dev)
222 		return -ENOMEM;
223 
224 	indio_dev->info = &maxim_thermocouple_info;
225 	indio_dev->name = MAXIM_THERMOCOUPLE_DRV_NAME;
226 	indio_dev->channels = chip->channels;
227 	indio_dev->available_scan_masks = chip->scan_masks;
228 	indio_dev->num_channels = chip->num_channels;
229 	indio_dev->modes = INDIO_DIRECT_MODE;
230 
231 	data = iio_priv(indio_dev);
232 	data->spi = spi;
233 	data->chip = chip;
234 
235 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
236 				maxim_thermocouple_trigger_handler, NULL);
237 	if (ret)
238 		return ret;
239 
240 	ret = iio_device_register(indio_dev);
241 	if (ret)
242 		goto error_unreg_buffer;
243 
244 	return 0;
245 
246 error_unreg_buffer:
247 	iio_triggered_buffer_cleanup(indio_dev);
248 
249 	return ret;
250 }
251 
252 static int maxim_thermocouple_remove(struct spi_device *spi)
253 {
254 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
255 
256 	iio_device_unregister(indio_dev);
257 	iio_triggered_buffer_cleanup(indio_dev);
258 
259 	return 0;
260 }
261 
262 static const struct spi_device_id maxim_thermocouple_id[] = {
263 	{"max6675", MAX6675},
264 	{"max31855", MAX31855},
265 	{},
266 };
267 MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id);
268 
269 static struct spi_driver maxim_thermocouple_driver = {
270 	.driver = {
271 		.name	= MAXIM_THERMOCOUPLE_DRV_NAME,
272 	},
273 	.probe		= maxim_thermocouple_probe,
274 	.remove		= maxim_thermocouple_remove,
275 	.id_table	= maxim_thermocouple_id,
276 };
277 module_spi_driver(maxim_thermocouple_driver);
278 
279 MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
280 MODULE_DESCRIPTION("Maxim thermocouple sensors");
281 MODULE_LICENSE("GPL");
282