xref: /linux/drivers/iio/temperature/tmp007.c (revision be709d48329a500621d2a05835283150ae137b45)
1 /*
2  * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
3  *
4  * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23@gmail.com>
5  *
6  * This file is subject to the terms and conditions of version 2 of
7  * the GNU General Public License.  See the file COPYING in the main
8  * directory of this archive for more details.
9  *
10  * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
11  *
12  * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
13  *
14  * Note:
15  * 1. This driver assumes that the sensor has been calibrated beforehand
16  * 2. Limit threshold events are enabled at the start
17  * 3. Operating mode: INT
18  *
19  */
20 
21 #include <linux/err.h>
22 #include <linux/i2c.h>
23 #include <linux/delay.h>
24 #include <linux/module.h>
25 #include <linux/pm.h>
26 #include <linux/bitops.h>
27 #include <linux/of.h>
28 #include <linux/irq.h>
29 #include <linux/interrupt.h>
30 
31 #include <linux/iio/iio.h>
32 #include <linux/iio/sysfs.h>
33 #include <linux/iio/events.h>
34 
35 #define TMP007_TDIE 0x01
36 #define TMP007_CONFIG 0x02
37 #define TMP007_TOBJECT 0x03
38 #define TMP007_STATUS 0x04
39 #define TMP007_STATUS_MASK 0x05
40 #define TMP007_TOBJ_HIGH_LIMIT 0x06
41 #define TMP007_TOBJ_LOW_LIMIT 0x07
42 #define TMP007_TDIE_HIGH_LIMIT 0x08
43 #define TMP007_TDIE_LOW_LIMIT 0x09
44 #define TMP007_MANUFACTURER_ID 0x1e
45 #define TMP007_DEVICE_ID 0x1f
46 
47 #define TMP007_CONFIG_CONV_EN BIT(12)
48 #define TMP007_CONFIG_TC_EN BIT(6)
49 #define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
50 #define TMP007_CONFIG_ALERT_EN BIT(8)
51 #define TMP007_CONFIG_CR_SHIFT 9
52 
53 /* Status register flags */
54 #define TMP007_STATUS_ALERT BIT(15)
55 #define TMP007_STATUS_CONV_READY BIT(14)
56 #define TMP007_STATUS_OHF BIT(13)
57 #define TMP007_STATUS_OLF BIT(12)
58 #define TMP007_STATUS_LHF BIT(11)
59 #define TMP007_STATUS_LLF BIT(10)
60 #define TMP007_STATUS_DATA_VALID BIT(9)
61 
62 #define TMP007_MANUFACTURER_MAGIC 0x5449
63 #define TMP007_DEVICE_MAGIC 0x0078
64 
65 #define TMP007_TEMP_SHIFT 2
66 
67 struct tmp007_data {
68 	struct i2c_client *client;
69 	struct mutex lock;
70 	u16 config;
71 	u16 status_mask;
72 };
73 
74 static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
75 					{0, 500000}, {0, 250000} };
76 
77 static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
78 {
79 	s32 ret;
80 	int tries = 50;
81 
82 	while (tries-- > 0) {
83 		ret = i2c_smbus_read_word_swapped(data->client,
84 			TMP007_STATUS);
85 		if (ret < 0)
86 			return ret;
87 		if ((ret & TMP007_STATUS_CONV_READY) &&
88 			!(ret & TMP007_STATUS_DATA_VALID))
89 				break;
90 		msleep(100);
91 	}
92 
93 	if (tries < 0)
94 		return -EIO;
95 
96 	return i2c_smbus_read_word_swapped(data->client, reg);
97 }
98 
99 static int tmp007_powerdown(struct tmp007_data *data)
100 {
101 	return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
102 			data->config & ~TMP007_CONFIG_CONV_EN);
103 }
104 
105 static int tmp007_read_raw(struct iio_dev *indio_dev,
106 		struct iio_chan_spec const *channel, int *val,
107 		int *val2, long mask)
108 {
109 	struct tmp007_data *data = iio_priv(indio_dev);
110 	s32 ret;
111 	int conv_rate;
112 
113 	switch (mask) {
114 	case IIO_CHAN_INFO_RAW:
115 		switch (channel->channel2) {
116 		case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
117 			ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
118 			if (ret < 0)
119 				return ret;
120 			break;
121 		case IIO_MOD_TEMP_OBJECT:
122 			ret = tmp007_read_temperature(data, TMP007_TOBJECT);
123 			if (ret < 0)
124 				return ret;
125 			break;
126 		default:
127 			return -EINVAL;
128 		}
129 
130 		*val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
131 
132 		return IIO_VAL_INT;
133 	case IIO_CHAN_INFO_SCALE:
134 		*val = 31;
135 		*val2 = 250000;
136 
137 		return IIO_VAL_INT_PLUS_MICRO;
138 	case IIO_CHAN_INFO_SAMP_FREQ:
139 		conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
140 				>> TMP007_CONFIG_CR_SHIFT;
141 		*val = tmp007_avgs[conv_rate][0];
142 		*val2 = tmp007_avgs[conv_rate][1];
143 
144 		return IIO_VAL_INT_PLUS_MICRO;
145 	default:
146 		return -EINVAL;
147 	}
148 }
149 
150 static int tmp007_write_raw(struct iio_dev *indio_dev,
151 		struct iio_chan_spec const *channel, int val,
152 		int val2, long mask)
153 {
154 	struct tmp007_data *data = iio_priv(indio_dev);
155 	int i;
156 	u16 tmp;
157 
158 	if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
159 		for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
160 			if ((val == tmp007_avgs[i][0]) &&
161 			(val2 == tmp007_avgs[i][1])) {
162 				tmp = data->config & ~TMP007_CONFIG_CR_MASK;
163 				tmp |= (i << TMP007_CONFIG_CR_SHIFT);
164 
165 				return i2c_smbus_write_word_swapped(data->client,
166 								TMP007_CONFIG,
167 								data->config = tmp);
168 			}
169 		}
170 	}
171 
172 	return -EINVAL;
173 }
174 
175 static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
176 {
177 	struct iio_dev *indio_dev = private;
178 	struct tmp007_data *data = iio_priv(indio_dev);
179 	int ret;
180 
181 	ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS);
182 	if ((ret < 0) || !(ret & (TMP007_STATUS_OHF | TMP007_STATUS_OLF |
183 				TMP007_STATUS_LHF | TMP007_STATUS_LLF)))
184 		return IRQ_NONE;
185 
186 	if (ret & TMP007_STATUS_OHF)
187 		iio_push_event(indio_dev,
188 				IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
189 					IIO_MOD_TEMP_OBJECT,
190 					IIO_EV_TYPE_THRESH,
191 					IIO_EV_DIR_RISING),
192 				iio_get_time_ns(indio_dev));
193 
194 	if (ret & TMP007_STATUS_OLF)
195 		iio_push_event(indio_dev,
196 				IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
197 					IIO_MOD_TEMP_OBJECT,
198 					IIO_EV_TYPE_THRESH,
199 					IIO_EV_DIR_FALLING),
200 				iio_get_time_ns(indio_dev));
201 
202 	if (ret & TMP007_STATUS_LHF)
203 		iio_push_event(indio_dev,
204 				IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
205 					IIO_MOD_TEMP_AMBIENT,
206 					IIO_EV_TYPE_THRESH,
207 					IIO_EV_DIR_RISING),
208 				iio_get_time_ns(indio_dev));
209 
210 	if (ret & TMP007_STATUS_LLF)
211 		iio_push_event(indio_dev,
212 				IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
213 					IIO_MOD_TEMP_AMBIENT,
214 					IIO_EV_TYPE_THRESH,
215 					IIO_EV_DIR_FALLING),
216 				iio_get_time_ns(indio_dev));
217 
218 	return IRQ_HANDLED;
219 }
220 
221 static int tmp007_write_event_config(struct iio_dev *indio_dev,
222 		const struct iio_chan_spec *chan, enum iio_event_type type,
223 		enum iio_event_direction dir, int state)
224 {
225 	struct tmp007_data *data = iio_priv(indio_dev);
226 	unsigned int status_mask;
227 	int ret;
228 
229 	switch (chan->channel2) {
230 	case IIO_MOD_TEMP_AMBIENT:
231 	if (dir == IIO_EV_DIR_RISING)
232 			status_mask = TMP007_STATUS_LHF;
233 		else
234 			status_mask = TMP007_STATUS_LLF;
235 		break;
236 	case IIO_MOD_TEMP_OBJECT:
237 		if (dir == IIO_EV_DIR_RISING)
238 			status_mask = TMP007_STATUS_OHF;
239 		else
240 			status_mask = TMP007_STATUS_OLF;
241 		break;
242 	default:
243 		return -EINVAL;
244 	}
245 
246 	mutex_lock(&data->lock);
247 	ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
248 	mutex_unlock(&data->lock);
249 	if (ret < 0)
250 		return ret;
251 
252 	if (state)
253 		ret |= status_mask;
254 	else
255 		ret &= ~status_mask;
256 
257 	return i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
258 					data->status_mask = ret);
259 }
260 
261 static int tmp007_read_event_config(struct iio_dev *indio_dev,
262 		const struct iio_chan_spec *chan, enum iio_event_type type,
263 		enum iio_event_direction dir)
264 {
265 	struct tmp007_data *data = iio_priv(indio_dev);
266 	unsigned int mask;
267 
268 	switch (chan->channel2) {
269 	case IIO_MOD_TEMP_AMBIENT:
270 		if (dir == IIO_EV_DIR_RISING)
271 			mask = TMP007_STATUS_LHF;
272 		else
273 			mask = TMP007_STATUS_LLF;
274 		break;
275 	case IIO_MOD_TEMP_OBJECT:
276 		if (dir == IIO_EV_DIR_RISING)
277 			mask = TMP007_STATUS_OHF;
278 		else
279 			mask = TMP007_STATUS_OLF;
280 		break;
281 	default:
282 		return -EINVAL;
283 	}
284 
285 	return !!(data->status_mask & mask);
286 }
287 
288 static int tmp007_read_thresh(struct iio_dev *indio_dev,
289 		const struct iio_chan_spec *chan, enum iio_event_type type,
290 		enum iio_event_direction dir, enum iio_event_info info,
291 		int *val, int *val2)
292 {
293 	struct tmp007_data *data = iio_priv(indio_dev);
294 	int ret;
295 	u8 reg;
296 
297 	switch (chan->channel2) {
298 	case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.5 degree Celsius */
299 		if (dir == IIO_EV_DIR_RISING)
300 			reg = TMP007_TDIE_HIGH_LIMIT;
301 		else
302 			reg = TMP007_TDIE_LOW_LIMIT;
303 		break;
304 	case IIO_MOD_TEMP_OBJECT:
305 		if (dir == IIO_EV_DIR_RISING)
306 			reg = TMP007_TOBJ_HIGH_LIMIT;
307 	else
308 			reg = TMP007_TOBJ_LOW_LIMIT;
309 		break;
310 	default:
311 		return -EINVAL;
312 	}
313 
314 	ret = i2c_smbus_read_word_swapped(data->client, reg);
315 	if (ret < 0)
316 		return ret;
317 
318 	/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
319 	*val = sign_extend32(ret, 15) >> 7;
320 
321 	return IIO_VAL_INT;
322 }
323 
324 static int tmp007_write_thresh(struct iio_dev *indio_dev,
325 		const struct iio_chan_spec *chan, enum iio_event_type type,
326 		enum iio_event_direction dir, enum iio_event_info info,
327 		int val, int val2)
328 {
329 	struct tmp007_data *data = iio_priv(indio_dev);
330 	u8 reg;
331 
332 	switch (chan->channel2) {
333 	case IIO_MOD_TEMP_AMBIENT:
334 		if (dir == IIO_EV_DIR_RISING)
335 			reg = TMP007_TDIE_HIGH_LIMIT;
336 		else
337 			reg = TMP007_TDIE_LOW_LIMIT;
338 		break;
339 	case IIO_MOD_TEMP_OBJECT:
340 		if (dir == IIO_EV_DIR_RISING)
341 			reg = TMP007_TOBJ_HIGH_LIMIT;
342 		else
343 			reg = TMP007_TOBJ_LOW_LIMIT;
344 		break;
345 	default:
346 		return -EINVAL;
347 	}
348 
349 	/* Full scale threshold value is +/- 256 degree Celsius */
350 	if (val < -256 || val > 255)
351 		return -EINVAL;
352 
353 	/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
354 	return i2c_smbus_write_word_swapped(data->client, reg, (val << 7));
355 }
356 
357 static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
358 
359 static struct attribute *tmp007_attributes[] = {
360 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
361 	NULL
362 };
363 
364 static const struct attribute_group tmp007_attribute_group = {
365 	.attrs = tmp007_attributes,
366 };
367 
368 static const struct iio_event_spec tmp007_obj_event[] = {
369 	{
370 		.type = IIO_EV_TYPE_THRESH,
371 		.dir = IIO_EV_DIR_RISING,
372 		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
373 			BIT(IIO_EV_INFO_ENABLE),
374 	},
375 	{
376 		.type = IIO_EV_TYPE_THRESH,
377 		.dir = IIO_EV_DIR_FALLING,
378 		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
379 			BIT(IIO_EV_INFO_ENABLE),
380 	},
381 };
382 
383 static const struct iio_event_spec tmp007_die_event[] = {
384 	{
385 		.type = IIO_EV_TYPE_THRESH,
386 		.dir = IIO_EV_DIR_RISING,
387 		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
388 			BIT(IIO_EV_INFO_ENABLE),
389 	},
390 	{
391 		.type = IIO_EV_TYPE_THRESH,
392 		.dir = IIO_EV_DIR_FALLING,
393 		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
394 			BIT(IIO_EV_INFO_ENABLE),
395 	},
396 };
397 
398 static const struct iio_chan_spec tmp007_channels[] = {
399 	{
400 		.type = IIO_TEMP,
401 		.modified = 1,
402 		.channel2 = IIO_MOD_TEMP_AMBIENT,
403 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
404 				BIT(IIO_CHAN_INFO_SCALE),
405 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
406 		.event_spec = tmp007_die_event,
407 		.num_event_specs = ARRAY_SIZE(tmp007_die_event),
408 	},
409 	{
410 		.type = IIO_TEMP,
411 		.modified = 1,
412 		.channel2 = IIO_MOD_TEMP_OBJECT,
413 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
414 				BIT(IIO_CHAN_INFO_SCALE),
415 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
416 		.event_spec = tmp007_obj_event,
417 		.num_event_specs = ARRAY_SIZE(tmp007_obj_event),
418 	}
419 };
420 
421 static const struct iio_info tmp007_info = {
422 	.read_raw = tmp007_read_raw,
423 	.write_raw = tmp007_write_raw,
424 	.read_event_config = tmp007_read_event_config,
425 	.write_event_config = tmp007_write_event_config,
426 	.read_event_value = tmp007_read_thresh,
427 	.write_event_value = tmp007_write_thresh,
428 	.attrs = &tmp007_attribute_group,
429 };
430 
431 static bool tmp007_identify(struct i2c_client *client)
432 {
433 	int manf_id, dev_id;
434 
435 	manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
436 	if (manf_id < 0)
437 		return false;
438 
439 	dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
440 	if (dev_id < 0)
441 		return false;
442 
443 	return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
444 }
445 
446 static int tmp007_probe(struct i2c_client *client,
447 			const struct i2c_device_id *tmp007_id)
448 {
449 	struct tmp007_data *data;
450 	struct iio_dev *indio_dev;
451 	int ret;
452 
453 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
454 		return -EOPNOTSUPP;
455 
456 	if (!tmp007_identify(client)) {
457 		dev_err(&client->dev, "TMP007 not found\n");
458 		return -ENODEV;
459 	}
460 
461 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
462 	if (!indio_dev)
463 		return -ENOMEM;
464 
465 	data = iio_priv(indio_dev);
466 	i2c_set_clientdata(client, indio_dev);
467 	data->client = client;
468 	mutex_init(&data->lock);
469 
470 	indio_dev->dev.parent = &client->dev;
471 	indio_dev->name = "tmp007";
472 	indio_dev->modes = INDIO_DIRECT_MODE;
473 	indio_dev->info = &tmp007_info;
474 
475 	indio_dev->channels = tmp007_channels;
476 	indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
477 
478 	/*
479 	 * Set Configuration register:
480 	 * 1. Conversion ON
481 	 * 2. ALERT enable
482 	 * 3. Transient correction enable
483 	 */
484 
485 	ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
486 	if (ret < 0)
487 		return ret;
488 
489 	data->config = ret;
490 	data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_ALERT_EN | TMP007_CONFIG_TC_EN);
491 
492 	ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
493 					data->config);
494 	if (ret < 0)
495 		return ret;
496 
497 	/*
498 	 * Only the following flags can activate ALERT pin. Data conversion/validity flags
499 	 * flags can still be polled for getting temperature data
500 	 *
501 	 * Set Status Mask register:
502 	 * 1. Object temperature high limit enable
503 	 * 2. Object temperature low limit enable
504 	 * 3. TDIE temperature high limit enable
505 	 * 4. TDIE temperature low limit enable
506 	 */
507 
508 	ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
509 	if (ret < 0)
510 		goto error_powerdown;
511 
512 	data->status_mask = ret;
513 	data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF
514 				| TMP007_STATUS_LHF | TMP007_STATUS_LLF);
515 
516 	ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, data->status_mask);
517 	if (ret < 0)
518 		goto error_powerdown;
519 
520 	if (client->irq) {
521 		ret = devm_request_threaded_irq(&client->dev, client->irq,
522 				NULL, tmp007_interrupt_handler,
523 				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
524 				tmp007_id->name, indio_dev);
525 		if (ret) {
526 			dev_err(&client->dev, "irq request error %d\n", -ret);
527 			goto error_powerdown;
528 		}
529 	}
530 
531 	return iio_device_register(indio_dev);
532 
533 error_powerdown:
534 	tmp007_powerdown(data);
535 
536 	return ret;
537 }
538 
539 static int tmp007_remove(struct i2c_client *client)
540 {
541 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
542 	struct tmp007_data *data = iio_priv(indio_dev);
543 
544 	iio_device_unregister(indio_dev);
545 	tmp007_powerdown(data);
546 
547 	return 0;
548 }
549 
550 #ifdef CONFIG_PM_SLEEP
551 static int tmp007_suspend(struct device *dev)
552 {
553 	struct tmp007_data *data = iio_priv(i2c_get_clientdata(
554 			to_i2c_client(dev)));
555 
556 	return tmp007_powerdown(data);
557 }
558 
559 static int tmp007_resume(struct device *dev)
560 {
561 	struct tmp007_data *data = iio_priv(i2c_get_clientdata(
562 			to_i2c_client(dev)));
563 
564 	return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
565 			data->config | TMP007_CONFIG_CONV_EN);
566 }
567 #endif
568 
569 static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
570 
571 static const struct of_device_id tmp007_of_match[] = {
572 	{ .compatible = "ti,tmp007", },
573 	{ },
574 };
575 MODULE_DEVICE_TABLE(of, tmp007_of_match);
576 
577 static const struct i2c_device_id tmp007_id[] = {
578 	{ "tmp007", 0 },
579 	{ }
580 };
581 MODULE_DEVICE_TABLE(i2c, tmp007_id);
582 
583 static struct i2c_driver tmp007_driver = {
584 	.driver = {
585 		.name	= "tmp007",
586 		.of_match_table = of_match_ptr(tmp007_of_match),
587 		.pm	= &tmp007_pm_ops,
588 	},
589 	.probe		= tmp007_probe,
590 	.remove		= tmp007_remove,
591 	.id_table	= tmp007_id,
592 };
593 module_i2c_driver(tmp007_driver);
594 
595 MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23@gmail.com>");
596 MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
597 MODULE_LICENSE("GPL");
598