Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * tmp006.c - Support for TI TMP006 IR thermopile sensor
4 *
5 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
6 *
7 * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
8 *
9 * (7-bit I2C slave address 0x40, changeable via ADR pins)
10 */
11
12#include <linux/err.h>
13#include <linux/i2c.h>
14#include <linux/delay.h>
15#include <linux/module.h>
16#include <linux/mod_devicetable.h>
17#include <linux/pm.h>
18#include <linux/bitops.h>
19
20#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>
22#include <linux/iio/trigger.h>
23#include <linux/iio/triggered_buffer.h>
24#include <linux/iio/trigger_consumer.h>
25
26#define TMP006_VOBJECT 0x00
27#define TMP006_TAMBIENT 0x01
28#define TMP006_CONFIG 0x02
29#define TMP006_MANUFACTURER_ID 0xfe
30#define TMP006_DEVICE_ID 0xff
31
32#define TMP006_TAMBIENT_SHIFT 2
33
34#define TMP006_CONFIG_RESET BIT(15)
35#define TMP006_CONFIG_DRDY_EN BIT(8)
36#define TMP006_CONFIG_DRDY BIT(7)
37
38#define TMP006_CONFIG_MOD_MASK GENMASK(14, 12)
39
40#define TMP006_CONFIG_CR_MASK GENMASK(11, 9)
41#define TMP006_CONFIG_CR_SHIFT 9
42
43#define TMP006_MANUFACTURER_MAGIC 0x5449
44#define TMP006_DEVICE_MAGIC 0x0067
45
46struct tmp006_data {
47 struct i2c_client *client;
48 u16 config;
49 struct iio_trigger *drdy_trig;
50};
51
52static int tmp006_read_measurement(struct tmp006_data *data, u8 reg)
53{
54 s32 ret;
55 int tries = 50;
56
57 while (tries-- > 0) {
58 ret = i2c_smbus_read_word_swapped(data->client,
59 TMP006_CONFIG);
60 if (ret < 0)
61 return ret;
62 if (ret & TMP006_CONFIG_DRDY)
63 break;
64 msleep(100);
65 }
66
67 if (tries < 0)
68 return -EIO;
69
70 return i2c_smbus_read_word_swapped(data->client, reg);
71}
72
73static const int tmp006_freqs[5][2] = { {4, 0}, {2, 0}, {1, 0},
74 {0, 500000}, {0, 250000} };
75
76static int tmp006_read_raw(struct iio_dev *indio_dev,
77 struct iio_chan_spec const *channel, int *val,
78 int *val2, long mask)
79{
80 struct tmp006_data *data = iio_priv(indio_dev);
81 s32 ret;
82 int cr;
83
84 switch (mask) {
85 case IIO_CHAN_INFO_RAW:
86 if (channel->type == IIO_VOLTAGE) {
87 /* LSB is 156.25 nV */
88 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
89 ret = tmp006_read_measurement(data, TMP006_VOBJECT);
90 if (ret < 0)
91 return ret;
92 }
93 *val = sign_extend32(ret, 15);
94 } else if (channel->type == IIO_TEMP) {
95 /* LSB is 0.03125 degrees Celsius */
96 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
97 ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
98 if (ret < 0)
99 return ret;
100 }
101 *val = sign_extend32(ret, 15) >> TMP006_TAMBIENT_SHIFT;
102 } else {
103 break;
104 }
105 return IIO_VAL_INT;
106 case IIO_CHAN_INFO_SCALE:
107 if (channel->type == IIO_VOLTAGE) {
108 *val = 0;
109 *val2 = 156250;
110 } else if (channel->type == IIO_TEMP) {
111 *val = 31;
112 *val2 = 250000;
113 } else {
114 break;
115 }
116 return IIO_VAL_INT_PLUS_MICRO;
117 case IIO_CHAN_INFO_SAMP_FREQ:
118 cr = (data->config & TMP006_CONFIG_CR_MASK)
119 >> TMP006_CONFIG_CR_SHIFT;
120 *val = tmp006_freqs[cr][0];
121 *val2 = tmp006_freqs[cr][1];
122 return IIO_VAL_INT_PLUS_MICRO;
123 default:
124 break;
125 }
126
127 return -EINVAL;
128}
129
130static int tmp006_write_raw(struct iio_dev *indio_dev,
131 struct iio_chan_spec const *chan,
132 int val,
133 int val2,
134 long mask)
135{
136 struct tmp006_data *data = iio_priv(indio_dev);
137 int ret, i;
138
139 if (mask != IIO_CHAN_INFO_SAMP_FREQ)
140 return -EINVAL;
141
142 for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++)
143 if ((val == tmp006_freqs[i][0]) &&
144 (val2 == tmp006_freqs[i][1])) {
145 ret = iio_device_claim_direct_mode(indio_dev);
146 if (ret)
147 return ret;
148
149 data->config &= ~TMP006_CONFIG_CR_MASK;
150 data->config |= i << TMP006_CONFIG_CR_SHIFT;
151
152 ret = i2c_smbus_write_word_swapped(data->client,
153 TMP006_CONFIG,
154 data->config);
155
156 iio_device_release_direct_mode(indio_dev);
157 return ret;
158 }
159 return -EINVAL;
160}
161
162static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
163
164static struct attribute *tmp006_attributes[] = {
165 &iio_const_attr_sampling_frequency_available.dev_attr.attr,
166 NULL
167};
168
169static const struct attribute_group tmp006_attribute_group = {
170 .attrs = tmp006_attributes,
171};
172
173static const struct iio_chan_spec tmp006_channels[] = {
174 {
175 .type = IIO_VOLTAGE,
176 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
177 BIT(IIO_CHAN_INFO_SCALE),
178 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
179 .scan_index = 0,
180 .scan_type = {
181 .sign = 's',
182 .realbits = 16,
183 .storagebits = 16,
184 .endianness = IIO_BE,
185 }
186 },
187 {
188 .type = IIO_TEMP,
189 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
190 BIT(IIO_CHAN_INFO_SCALE),
191 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
192 .scan_index = 1,
193 .scan_type = {
194 .sign = 's',
195 .realbits = 14,
196 .storagebits = 16,
197 .shift = TMP006_TAMBIENT_SHIFT,
198 .endianness = IIO_BE,
199 }
200 },
201 IIO_CHAN_SOFT_TIMESTAMP(2),
202};
203
204static const struct iio_info tmp006_info = {
205 .read_raw = tmp006_read_raw,
206 .write_raw = tmp006_write_raw,
207 .attrs = &tmp006_attribute_group,
208};
209
210static bool tmp006_check_identification(struct i2c_client *client)
211{
212 int mid, did;
213
214 mid = i2c_smbus_read_word_swapped(client, TMP006_MANUFACTURER_ID);
215 if (mid < 0)
216 return false;
217
218 did = i2c_smbus_read_word_swapped(client, TMP006_DEVICE_ID);
219 if (did < 0)
220 return false;
221
222 return mid == TMP006_MANUFACTURER_MAGIC && did == TMP006_DEVICE_MAGIC;
223}
224
225static int tmp006_power(struct device *dev, bool up)
226{
227 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
228 struct tmp006_data *data = iio_priv(indio_dev);
229
230 if (up)
231 data->config |= TMP006_CONFIG_MOD_MASK;
232 else
233 data->config &= ~TMP006_CONFIG_MOD_MASK;
234
235 return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
236 data->config);
237}
238
239static void tmp006_powerdown_cleanup(void *dev)
240{
241 tmp006_power(dev, false);
242}
243
244static irqreturn_t tmp006_trigger_handler(int irq, void *p)
245{
246 struct iio_poll_func *pf = p;
247 struct iio_dev *indio_dev = pf->indio_dev;
248 struct tmp006_data *data = iio_priv(indio_dev);
249 struct {
250 s16 channels[2];
251 s64 ts __aligned(8);
252 } scan;
253 s32 ret;
254
255 memset(&scan, 0, sizeof(scan));
256
257 ret = i2c_smbus_read_word_data(data->client, TMP006_VOBJECT);
258 if (ret < 0)
259 goto err;
260 scan.channels[0] = ret;
261
262 ret = i2c_smbus_read_word_data(data->client, TMP006_TAMBIENT);
263 if (ret < 0)
264 goto err;
265 scan.channels[1] = ret;
266
267 iio_push_to_buffers_with_timestamp(indio_dev, &scan,
268 iio_get_time_ns(indio_dev));
269err:
270 iio_trigger_notify_done(indio_dev->trig);
271 return IRQ_HANDLED;
272}
273
274static int tmp006_set_trigger_state(struct iio_trigger *trig, bool state)
275{
276 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
277 struct tmp006_data *data = iio_priv(indio_dev);
278
279 if (state)
280 data->config |= TMP006_CONFIG_DRDY_EN;
281 else
282 data->config &= ~TMP006_CONFIG_DRDY_EN;
283
284 return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
285 data->config);
286}
287
288static const struct iio_trigger_ops tmp006_trigger_ops = {
289 .set_trigger_state = tmp006_set_trigger_state,
290};
291
292static const unsigned long tmp006_scan_masks[] = { 0x3, 0 };
293
294static int tmp006_probe(struct i2c_client *client)
295{
296 struct iio_dev *indio_dev;
297 struct tmp006_data *data;
298 int ret;
299
300 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
301 return -EOPNOTSUPP;
302
303 if (!tmp006_check_identification(client)) {
304 dev_err(&client->dev, "no TMP006 sensor\n");
305 return -ENODEV;
306 }
307
308 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
309 if (!indio_dev)
310 return -ENOMEM;
311
312 data = iio_priv(indio_dev);
313 i2c_set_clientdata(client, indio_dev);
314 data->client = client;
315
316 indio_dev->name = dev_name(&client->dev);
317 indio_dev->modes = INDIO_DIRECT_MODE;
318 indio_dev->info = &tmp006_info;
319
320 indio_dev->channels = tmp006_channels;
321 indio_dev->num_channels = ARRAY_SIZE(tmp006_channels);
322 indio_dev->available_scan_masks = tmp006_scan_masks;
323
324 ret = i2c_smbus_read_word_swapped(data->client, TMP006_CONFIG);
325 if (ret < 0)
326 return ret;
327 data->config = ret;
328
329 if ((ret & TMP006_CONFIG_MOD_MASK) != TMP006_CONFIG_MOD_MASK) {
330 ret = tmp006_power(&client->dev, true);
331 if (ret < 0)
332 return ret;
333 }
334
335 ret = devm_add_action_or_reset(&client->dev, tmp006_powerdown_cleanup,
336 &client->dev);
337 if (ret < 0)
338 return ret;
339
340 if (client->irq > 0) {
341 data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
342 "%s-dev%d",
343 indio_dev->name,
344 iio_device_id(indio_dev));
345 if (!data->drdy_trig)
346 return -ENOMEM;
347
348 data->drdy_trig->ops = &tmp006_trigger_ops;
349 iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
350 ret = iio_trigger_register(data->drdy_trig);
351 if (ret)
352 return ret;
353
354 indio_dev->trig = iio_trigger_get(data->drdy_trig);
355
356 ret = devm_request_threaded_irq(&client->dev, client->irq,
357 iio_trigger_generic_data_rdy_poll,
358 NULL,
359 IRQF_ONESHOT,
360 "tmp006_irq",
361 data->drdy_trig);
362 if (ret < 0)
363 return ret;
364 }
365
366 ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
367 tmp006_trigger_handler, NULL);
368 if (ret < 0)
369 return ret;
370
371 return devm_iio_device_register(&client->dev, indio_dev);
372}
373
374static int tmp006_suspend(struct device *dev)
375{
376 return tmp006_power(dev, false);
377}
378
379static int tmp006_resume(struct device *dev)
380{
381 return tmp006_power(dev, true);
382}
383
384static DEFINE_SIMPLE_DEV_PM_OPS(tmp006_pm_ops, tmp006_suspend, tmp006_resume);
385
386static const struct of_device_id tmp006_of_match[] = {
387 { .compatible = "ti,tmp006" },
388 { }
389};
390MODULE_DEVICE_TABLE(of, tmp006_of_match);
391
392static const struct i2c_device_id tmp006_id[] = {
393 { "tmp006" },
394 { }
395};
396MODULE_DEVICE_TABLE(i2c, tmp006_id);
397
398static struct i2c_driver tmp006_driver = {
399 .driver = {
400 .name = "tmp006",
401 .of_match_table = tmp006_of_match,
402 .pm = pm_sleep_ptr(&tmp006_pm_ops),
403 },
404 .probe = tmp006_probe,
405 .id_table = tmp006_id,
406};
407module_i2c_driver(tmp006_driver);
408
409MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
410MODULE_DESCRIPTION("TI TMP006 IR thermopile sensor driver");
411MODULE_LICENSE("GPL");