blob: 96cbb17bc2cd9340442d5d837d57af5e1e3b3f0d [file] [log] [blame]
Sonic Zhangddaecd52010-10-27 21:43:55 -04001/*
2 * AD7291 digital temperature sensor driver supporting AD7291
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/interrupt.h>
10#include <linux/gpio.h>
Sonic Zhangddaecd52010-10-27 21:43:55 -040011#include <linux/device.h>
12#include <linux/kernel.h>
13#include <linux/slab.h>
14#include <linux/sysfs.h>
15#include <linux/list.h>
16#include <linux/i2c.h>
Sonic Zhangddaecd52010-10-27 21:43:55 -040017
18#include "../iio.h"
19#include "../sysfs.h"
20
21/*
22 * AD7291 registers definition
23 */
24#define AD7291_COMMAND 0
25#define AD7291_VOLTAGE 1
26#define AD7291_T_SENSE 2
27#define AD7291_T_AVERAGE 3
28#define AD7291_VOLTAGE_LIMIT_BASE 4
29#define AD7291_VOLTAGE_LIMIT_COUNT 8
30#define AD7291_T_SENSE_HIGH 0x1c
31#define AD7291_T_SENSE_LOW 0x1d
32#define AD7291_T_SENSE_HYST 0x1e
33#define AD7291_VOLTAGE_ALERT_STATUS 0x1f
34#define AD7291_T_ALERT_STATUS 0x20
35
36/*
37 * AD7291 command
38 */
39#define AD7291_AUTOCYCLE 0x1
40#define AD7291_RESET 0x2
41#define AD7291_ALART_CLEAR 0x4
42#define AD7291_ALART_POLARITY 0x8
43#define AD7291_EXT_REF 0x10
44#define AD7291_NOISE_DELAY 0x20
45#define AD7291_T_SENSE_MASK 0x40
46#define AD7291_VOLTAGE_MASK 0xff00
47#define AD7291_VOLTAGE_OFFSET 0x8
48
49/*
50 * AD7291 value masks
51 */
52#define AD7291_CHANNEL_MASK 0xf000
53#define AD7291_VALUE_MASK 0xfff
54#define AD7291_T_VALUE_SIGN 0x400
55#define AD7291_T_VALUE_FLOAT_OFFSET 2
56#define AD7291_T_VALUE_FLOAT_MASK 0x2
57
58/*
59 * struct ad7291_chip_info - chip specifc information
60 */
61
62struct ad7291_chip_info {
Sonic Zhangddaecd52010-10-27 21:43:55 -040063 struct i2c_client *client;
Sonic Zhangddaecd52010-10-27 21:43:55 -040064 u16 command;
65 u8 channels; /* Active voltage channels */
66};
67
68/*
69 * struct ad7291_chip_info - chip specifc information
70 */
71
72struct ad7291_limit_regs {
73 u16 data_high;
74 u16 data_low;
75 u16 hysteresis;
76};
77
78/*
79 * ad7291 register access by I2C
80 */
81static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
82{
83 struct i2c_client *client = chip->client;
84 int ret = 0;
85
86 ret = i2c_smbus_read_word_data(client, reg);
87 if (ret < 0) {
88 dev_err(&client->dev, "I2C read error\n");
89 return ret;
90 }
91
92 *data = swab16((u16)ret);
93
94 return 0;
95}
96
97static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
98{
99 struct i2c_client *client = chip->client;
100 int ret = 0;
101
102 ret = i2c_smbus_write_word_data(client, reg, swab16(data));
103 if (ret < 0)
104 dev_err(&client->dev, "I2C write error\n");
105
106 return ret;
107}
108
109/* Returns negative errno, or else the number of words read. */
110static int ad7291_i2c_read_data(struct ad7291_chip_info *chip, u8 reg, u16 *data)
111{
112 struct i2c_client *client = chip->client;
113 u8 commands[4];
114 int ret = 0;
115 int i, count;
116
117 if (reg == AD7291_T_SENSE || reg == AD7291_T_AVERAGE)
118 count = 2;
119 else if (reg == AD7291_VOLTAGE) {
120 if (!chip->channels) {
121 dev_err(&client->dev, "No voltage channel is selected.\n");
122 return -EINVAL;
123 }
124 count = 2 + chip->channels * 2;
125 } else {
126 dev_err(&client->dev, "I2C wrong data register\n");
127 return -EINVAL;
128 }
129
130 commands[0] = 0;
131 commands[1] = (chip->command >> 8) & 0xff;
132 commands[2] = chip->command & 0xff;
133 commands[3] = reg;
134
135 ret = i2c_master_send(client, commands, 4);
136 if (ret < 0) {
137 dev_err(&client->dev, "I2C master send error\n");
138 return ret;
139 }
140
141 ret = i2c_master_recv(client, (u8 *)data, count);
142 if (ret < 0) {
143 dev_err(&client->dev, "I2C master receive error\n");
144 return ret;
145 }
146 ret >>= 2;
147
148 for (i = 0; i < ret; i++)
149 data[i] = swab16(data[i]);
150
151 return ret;
152}
153
154static ssize_t ad7291_show_mode(struct device *dev,
155 struct device_attribute *attr,
156 char *buf)
157{
158 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100159 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400160
161 if (chip->command & AD7291_AUTOCYCLE)
162 return sprintf(buf, "autocycle\n");
163 else
164 return sprintf(buf, "command\n");
165}
166
167static ssize_t ad7291_store_mode(struct device *dev,
168 struct device_attribute *attr,
169 const char *buf,
170 size_t len)
171{
172 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100173 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400174 u16 command;
175 int ret;
176
177 command = chip->command & (~AD7291_AUTOCYCLE);
178 if (strcmp(buf, "autocycle"))
179 command |= AD7291_AUTOCYCLE;
180
181 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
182 if (ret)
183 return -EIO;
184
185 chip->command = command;
186
187 return ret;
188}
189
190static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
191 ad7291_show_mode,
192 ad7291_store_mode,
193 0);
194
195static ssize_t ad7291_show_available_modes(struct device *dev,
196 struct device_attribute *attr,
197 char *buf)
198{
199 return sprintf(buf, "command\nautocycle\n");
200}
201
202static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7291_show_available_modes, NULL, 0);
203
204static ssize_t ad7291_store_reset(struct device *dev,
205 struct device_attribute *attr,
206 const char *buf,
207 size_t len)
208{
209 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100210 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400211 u16 command;
212 int ret;
213
214 command = chip->command | AD7291_RESET;
215
216 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
217 if (ret)
218 return -EIO;
219
220 return ret;
221}
222
223static IIO_DEVICE_ATTR(reset, S_IWUSR,
224 NULL,
225 ad7291_store_reset,
226 0);
227
228static ssize_t ad7291_show_ext_ref(struct device *dev,
229 struct device_attribute *attr,
230 char *buf)
231{
232 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100233 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400234
235 return sprintf(buf, "%d\n", !!(chip->command & AD7291_EXT_REF));
236}
237
238static ssize_t ad7291_store_ext_ref(struct device *dev,
239 struct device_attribute *attr,
240 const char *buf,
241 size_t len)
242{
243 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100244 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400245 u16 command;
246 int ret;
247
248 command = chip->command & (~AD7291_EXT_REF);
249 if (strcmp(buf, "1"))
250 command |= AD7291_EXT_REF;
251
252 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
253 if (ret)
254 return -EIO;
255
256 chip->command = command;
257
258 return ret;
259}
260
261static IIO_DEVICE_ATTR(ext_ref, S_IRUGO | S_IWUSR,
262 ad7291_show_ext_ref,
263 ad7291_store_ext_ref,
264 0);
265
266static ssize_t ad7291_show_noise_delay(struct device *dev,
267 struct device_attribute *attr,
268 char *buf)
269{
270 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100271 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400272
273 return sprintf(buf, "%d\n", !!(chip->command & AD7291_NOISE_DELAY));
274}
275
276static ssize_t ad7291_store_noise_delay(struct device *dev,
277 struct device_attribute *attr,
278 const char *buf,
279 size_t len)
280{
281 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100282 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400283 u16 command;
284 int ret;
285
286 command = chip->command & (~AD7291_NOISE_DELAY);
287 if (strcmp(buf, "1"))
288 command |= AD7291_NOISE_DELAY;
289
290 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
291 if (ret)
292 return -EIO;
293
294 chip->command = command;
295
296 return ret;
297}
298
299static IIO_DEVICE_ATTR(noise_delay, S_IRUGO | S_IWUSR,
300 ad7291_show_noise_delay,
301 ad7291_store_noise_delay,
302 0);
303
304static ssize_t ad7291_show_t_sense(struct device *dev,
305 struct device_attribute *attr,
306 char *buf)
307{
308 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100309 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400310 u16 data;
311 char sign = ' ';
312 int ret;
313
314 ret = ad7291_i2c_read_data(chip, AD7291_T_SENSE, &data);
315 if (ret)
316 return -EIO;
317
318 if (data & AD7291_T_VALUE_SIGN) {
319 /* convert supplement to positive value */
320 data = (AD7291_T_VALUE_SIGN << 1) - data;
321 sign = '-';
322 }
323
324 return sprintf(buf, "%c%d.%.2d\n", sign,
325 (data >> AD7291_T_VALUE_FLOAT_OFFSET),
326 (data & AD7291_T_VALUE_FLOAT_MASK) * 25);
327}
328
329static IIO_DEVICE_ATTR(t_sense, S_IRUGO, ad7291_show_t_sense, NULL, 0);
330
331static ssize_t ad7291_show_t_average(struct device *dev,
332 struct device_attribute *attr,
333 char *buf)
334{
335 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100336 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400337 u16 data;
338 char sign = ' ';
339 int ret;
340
341 ret = ad7291_i2c_read_data(chip, AD7291_T_AVERAGE, &data);
342 if (ret)
343 return -EIO;
344
345 if (data & AD7291_T_VALUE_SIGN) {
346 /* convert supplement to positive value */
347 data = (AD7291_T_VALUE_SIGN << 1) - data;
348 sign = '-';
349 }
350
351 return sprintf(buf, "%c%d.%.2d\n", sign,
352 (data >> AD7291_T_VALUE_FLOAT_OFFSET),
353 (data & AD7291_T_VALUE_FLOAT_MASK) * 25);
354}
355
356static IIO_DEVICE_ATTR(t_average, S_IRUGO, ad7291_show_t_average, NULL, 0);
357
358static ssize_t ad7291_show_voltage(struct device *dev,
359 struct device_attribute *attr,
360 char *buf)
361{
362 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100363 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400364 u16 data[AD7291_VOLTAGE_LIMIT_COUNT];
365 int i, size, ret;
366
367 ret = ad7291_i2c_read_data(chip, AD7291_VOLTAGE, data);
368 if (ret)
369 return -EIO;
370
371 for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
372 if (chip->command & (AD7291_T_SENSE_MASK << i)) {
373 ret = sprintf(buf, "channel[%d]=%d\n", i,
374 data[i] & AD7291_VALUE_MASK);
375 if (ret < 0)
376 break;
377 buf += ret;
378 size += ret;
379 }
380 }
381
382 return size;
383}
384
385static IIO_DEVICE_ATTR(voltage, S_IRUGO, ad7291_show_voltage, NULL, 0);
386
387static ssize_t ad7291_show_channel_mask(struct device *dev,
388 struct device_attribute *attr,
389 char *buf)
390{
391 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100392 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400393
394 return sprintf(buf, "0x%x\n", (chip->command & AD7291_VOLTAGE_MASK) >>
395 AD7291_VOLTAGE_OFFSET);
396}
397
398static ssize_t ad7291_store_channel_mask(struct device *dev,
399 struct device_attribute *attr,
400 const char *buf,
401 size_t len)
402{
403 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100404 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400405 u16 command;
406 unsigned long data;
407 int i, ret;
408
409 ret = strict_strtoul(buf, 16, &data);
410 if (ret || data > 0xff)
411 return -EINVAL;
412
413 command = chip->command & (~AD7291_VOLTAGE_MASK);
414 command |= data << AD7291_VOLTAGE_OFFSET;
415
416 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
417 if (ret)
418 return -EIO;
419
420 chip->command = command;
421
422 for (i = 0, chip->channels = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
423 if (chip->command & (AD7291_T_SENSE_MASK << i))
424 chip->channels++;
425 }
426
427 return ret;
428}
429
430static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR,
431 ad7291_show_channel_mask,
432 ad7291_store_channel_mask,
433 0);
434
Sonic Zhangddaecd52010-10-27 21:43:55 -0400435static struct attribute *ad7291_attributes[] = {
436 &iio_dev_attr_available_modes.dev_attr.attr,
437 &iio_dev_attr_mode.dev_attr.attr,
438 &iio_dev_attr_reset.dev_attr.attr,
439 &iio_dev_attr_ext_ref.dev_attr.attr,
440 &iio_dev_attr_noise_delay.dev_attr.attr,
441 &iio_dev_attr_t_sense.dev_attr.attr,
442 &iio_dev_attr_t_average.dev_attr.attr,
443 &iio_dev_attr_voltage.dev_attr.attr,
444 &iio_dev_attr_channel_mask.dev_attr.attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400445 NULL,
446};
447
448static const struct attribute_group ad7291_attribute_group = {
449 .attrs = ad7291_attributes,
450};
451
452/*
453 * temperature bound events
454 */
455
Jonathan Cameron58c03232011-05-18 14:41:11 +0100456static irqreturn_t ad7291_event_handler(int irq, void *private)
Sonic Zhangddaecd52010-10-27 21:43:55 -0400457{
Jonathan Cameron58c03232011-05-18 14:41:11 +0100458 struct iio_dev *indio_dev = private;
Jonathan Camerond4397972011-06-27 13:07:23 +0100459 struct ad7291_chip_info *chip = iio_priv(private);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400460 u16 t_status, v_status;
461 u16 command;
462 int i;
Jonathan Cameron58c03232011-05-18 14:41:11 +0100463 s64 timestamp = iio_get_time_ns();
Sonic Zhangddaecd52010-10-27 21:43:55 -0400464
465 if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100466 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400467
468 if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100469 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400470
471 if (!(t_status || v_status))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100472 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400473
474 command = chip->command | AD7291_ALART_CLEAR;
475 ad7291_i2c_write(chip, AD7291_COMMAND, command);
476
477 command = chip->command & ~AD7291_ALART_CLEAR;
478 ad7291_i2c_write(chip, AD7291_COMMAND, command);
479
Jonathan Cameronb206c3b2011-05-18 14:42:15 +0100480 if (t_status & (1 << 0))
481 iio_push_event(indio_dev, 0,
482 IIO_UNMOD_EVENT_CODE(IIO_TEMP,
483 0,
484 IIO_EV_TYPE_THRESH,
485 IIO_EV_DIR_FALLING),
486 timestamp);
487 if (t_status & (1 << 1))
488 iio_push_event(indio_dev, 0,
489 IIO_UNMOD_EVENT_CODE(IIO_TEMP,
490 0,
491 IIO_EV_TYPE_THRESH,
492 IIO_EV_DIR_RISING),
493 timestamp);
494 if (t_status & (1 << 2))
495 iio_push_event(indio_dev, 0,
496 IIO_UNMOD_EVENT_CODE(IIO_TEMP,
497 0,
498 IIO_EV_TYPE_THRESH,
499 IIO_EV_DIR_FALLING),
500 timestamp);
501 if (t_status & (1 << 3))
502 iio_push_event(indio_dev, 0,
503 IIO_UNMOD_EVENT_CODE(IIO_TEMP,
504 0,
505 IIO_EV_TYPE_THRESH,
506 IIO_EV_DIR_RISING),
507 timestamp);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400508
Jonathan Cameronb206c3b2011-05-18 14:42:15 +0100509 for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) {
Sonic Zhangddaecd52010-10-27 21:43:55 -0400510 if (v_status & (1 << i))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100511 iio_push_event(indio_dev, 0,
Jonathan Cameronb206c3b2011-05-18 14:42:15 +0100512 IIO_UNMOD_EVENT_CODE(IIO_IN,
513 i/2,
514 IIO_EV_TYPE_THRESH,
515 IIO_EV_DIR_FALLING),
516 timestamp);
517 if (v_status & (1 << (i + 1)))
518 iio_push_event(indio_dev, 0,
519 IIO_UNMOD_EVENT_CODE(IIO_IN,
520 i/2,
521 IIO_EV_TYPE_THRESH,
522 IIO_EV_DIR_RISING),
523 timestamp);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400524 }
Jonathan Cameron58c03232011-05-18 14:41:11 +0100525
526 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400527}
528
Sonic Zhangddaecd52010-10-27 21:43:55 -0400529static inline ssize_t ad7291_show_t_bound(struct device *dev,
530 struct device_attribute *attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400531 char *buf)
532{
533 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100534 struct ad7291_chip_info *chip = iio_priv(dev_info);
Jonathan Cameron58c03232011-05-18 14:41:11 +0100535 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400536 u16 data;
537 char sign = ' ';
538 int ret;
539
Jonathan Cameron58c03232011-05-18 14:41:11 +0100540 ret = ad7291_i2c_read(chip, this_attr->address, &data);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400541 if (ret)
542 return -EIO;
543
544 data &= AD7291_VALUE_MASK;
545 if (data & AD7291_T_VALUE_SIGN) {
546 /* convert supplement to positive value */
547 data = (AD7291_T_VALUE_SIGN << 1) - data;
548 sign = '-';
549 }
550
551 return sprintf(buf, "%c%d.%.2d\n", sign,
552 data >> AD7291_T_VALUE_FLOAT_OFFSET,
553 (data & AD7291_T_VALUE_FLOAT_MASK) * 25);
554}
555
556static inline ssize_t ad7291_set_t_bound(struct device *dev,
557 struct device_attribute *attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400558 const char *buf,
559 size_t len)
560{
561 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100562 struct ad7291_chip_info *chip = iio_priv(dev_info);
Jonathan Cameron58c03232011-05-18 14:41:11 +0100563 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400564 long tmp1, tmp2;
565 u16 data;
566 char *pos;
567 int ret;
568
569 pos = strchr(buf, '.');
570
571 ret = strict_strtol(buf, 10, &tmp1);
572
573 if (ret || tmp1 > 127 || tmp1 < -128)
574 return -EINVAL;
575
576 if (pos) {
577 len = strlen(pos);
578 if (len > AD7291_T_VALUE_FLOAT_OFFSET)
579 len = AD7291_T_VALUE_FLOAT_OFFSET;
580 pos[len] = 0;
581 ret = strict_strtol(pos, 10, &tmp2);
582
583 if (!ret)
584 tmp2 = (tmp2 / 25) * 25;
585 }
586
587 if (tmp1 < 0)
588 data = (u16)(-tmp1);
589 else
590 data = (u16)tmp1;
591 data = (data << AD7291_T_VALUE_FLOAT_OFFSET) |
592 (tmp2 & AD7291_T_VALUE_FLOAT_MASK);
593 if (tmp1 < 0)
594 /* convert positive value to supplyment */
595 data = (AD7291_T_VALUE_SIGN << 1) - data;
596
Jonathan Cameron58c03232011-05-18 14:41:11 +0100597 ret = ad7291_i2c_write(chip, this_attr->address, data);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400598 if (ret)
599 return -EIO;
600
601 return ret;
602}
603
Sonic Zhangddaecd52010-10-27 21:43:55 -0400604static inline ssize_t ad7291_show_v_bound(struct device *dev,
605 struct device_attribute *attr,
606 u8 bound_reg,
607 char *buf)
608{
609 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100610 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400611 u16 data;
612 int ret;
613
614 if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE ||
615 bound_reg >= AD7291_VOLTAGE_LIMIT_BASE +
616 AD7291_VOLTAGE_LIMIT_COUNT)
617 return -EINVAL;
618
619 ret = ad7291_i2c_read(chip, bound_reg, &data);
620 if (ret)
621 return -EIO;
622
623 data &= AD7291_VALUE_MASK;
624
625 return sprintf(buf, "%d\n", data);
626}
627
628static inline ssize_t ad7291_set_v_bound(struct device *dev,
629 struct device_attribute *attr,
630 u8 bound_reg,
631 const char *buf,
632 size_t len)
633{
634 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100635 struct ad7291_chip_info *chip = iio_priv(dev_info);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400636 unsigned long value;
637 u16 data;
638 int ret;
639
640 if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE ||
641 bound_reg >= AD7291_VOLTAGE_LIMIT_BASE +
642 AD7291_VOLTAGE_LIMIT_COUNT)
643 return -EINVAL;
644
645 ret = strict_strtoul(buf, 10, &value);
646
647 if (ret || value >= 4096)
648 return -EINVAL;
649
650 data = (u16)value;
651 ret = ad7291_i2c_write(chip, bound_reg, data);
652 if (ret)
653 return -EIO;
654
655 return ret;
656}
657
Jonathan Cameron58c03232011-05-18 14:41:11 +0100658static IIO_DEVICE_ATTR(t_sense_high_value,
659 S_IRUGO | S_IWUSR,
660 ad7291_show_t_bound, ad7291_set_t_bound,
661 AD7291_T_SENSE_HIGH);
662static IIO_DEVICE_ATTR(t_sense_low_value,
663 S_IRUGO | S_IWUSR,
664 ad7291_show_t_bound, ad7291_set_t_bound,
665 AD7291_T_SENSE_LOW);
666static IIO_DEVICE_ATTR(t_sense_hyst_value,
667 S_IRUGO | S_IWUSR,
668 ad7291_show_t_bound, ad7291_set_t_bound,
669 AD7291_T_SENSE_HYST);
670static IIO_DEVICE_ATTR(v0_high,
671 S_IRUGO | S_IWUSR,
672 ad7291_show_t_bound, ad7291_set_t_bound, 0x04);
673static IIO_DEVICE_ATTR(v0_low,
674 S_IRUGO | S_IWUSR,
675 ad7291_show_t_bound, ad7291_set_t_bound, 0x05);
676static IIO_DEVICE_ATTR(v0_hyst,
677 S_IRUGO | S_IWUSR,
678 ad7291_show_t_bound, ad7291_set_t_bound, 0x06);
679static IIO_DEVICE_ATTR(v1_high,
680 S_IRUGO | S_IWUSR,
681 ad7291_show_t_bound, ad7291_set_t_bound, 0x07);
682static IIO_DEVICE_ATTR(v1_low,
683 S_IRUGO | S_IWUSR,
684 ad7291_show_t_bound, ad7291_set_t_bound, 0x08);
685static IIO_DEVICE_ATTR(v1_hyst,
686 S_IRUGO | S_IWUSR,
687 ad7291_show_t_bound, ad7291_set_t_bound, 0x09);
688static IIO_DEVICE_ATTR(v2_high,
689 S_IRUGO | S_IWUSR,
690 ad7291_show_t_bound, ad7291_set_t_bound, 0x0A);
691static IIO_DEVICE_ATTR(v2_low,
692 S_IRUGO | S_IWUSR,
693 ad7291_show_t_bound, ad7291_set_t_bound, 0x0B);
694static IIO_DEVICE_ATTR(v2_hyst,
695 S_IRUGO | S_IWUSR,
696 ad7291_show_t_bound, ad7291_set_t_bound, 0x0C);
697static IIO_DEVICE_ATTR(v3_high,
698 S_IRUGO | S_IWUSR,
699 /* Datasheet suggests this one and this one only
700 has the registers in different order */
701 ad7291_show_t_bound, ad7291_set_t_bound, 0x0E);
702static IIO_DEVICE_ATTR(v3_low,
703 S_IRUGO | S_IWUSR,
704 ad7291_show_t_bound, ad7291_set_t_bound, 0x0D);
705static IIO_DEVICE_ATTR(v3_hyst,
706 S_IRUGO | S_IWUSR,
707 ad7291_show_t_bound, ad7291_set_t_bound, 0x0F);
708static IIO_DEVICE_ATTR(v4_high,
709 S_IRUGO | S_IWUSR,
710 ad7291_show_t_bound, ad7291_set_t_bound, 0x10);
711static IIO_DEVICE_ATTR(v4_low,
712 S_IRUGO | S_IWUSR,
713 ad7291_show_t_bound, ad7291_set_t_bound, 0x11);
714static IIO_DEVICE_ATTR(v4_hyst,
715 S_IRUGO | S_IWUSR,
716 ad7291_show_t_bound, ad7291_set_t_bound, 0x12);
717static IIO_DEVICE_ATTR(v5_high,
718 S_IRUGO | S_IWUSR,
719 ad7291_show_t_bound, ad7291_set_t_bound, 0x13);
720static IIO_DEVICE_ATTR(v5_low,
721 S_IRUGO | S_IWUSR,
722 ad7291_show_t_bound, ad7291_set_t_bound, 0x14);
723static IIO_DEVICE_ATTR(v5_hyst,
724 S_IRUGO | S_IWUSR,
725 ad7291_show_t_bound, ad7291_set_t_bound, 0x15);
726static IIO_DEVICE_ATTR(v6_high,
727 S_IRUGO | S_IWUSR,
728 ad7291_show_t_bound, ad7291_set_t_bound, 0x16);
729static IIO_DEVICE_ATTR(v6_low,
730 S_IRUGO | S_IWUSR,
731 ad7291_show_t_bound, ad7291_set_t_bound, 0x17);
732static IIO_DEVICE_ATTR(v6_hyst,
733 S_IRUGO | S_IWUSR,
734 ad7291_show_t_bound, ad7291_set_t_bound, 0x18);
735static IIO_DEVICE_ATTR(v7_high,
736 S_IRUGO | S_IWUSR,
737 ad7291_show_t_bound, ad7291_set_t_bound, 0x19);
738static IIO_DEVICE_ATTR(v7_low,
739 S_IRUGO | S_IWUSR,
740 ad7291_show_t_bound, ad7291_set_t_bound, 0x1A);
741static IIO_DEVICE_ATTR(v7_hyst,
742 S_IRUGO | S_IWUSR,
743 ad7291_show_t_bound, ad7291_set_t_bound, 0x1B);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400744
745static struct attribute *ad7291_event_attributes[] = {
Jonathan Cameron58c03232011-05-18 14:41:11 +0100746 &iio_dev_attr_t_sense_high_value.dev_attr.attr,
747 &iio_dev_attr_t_sense_low_value.dev_attr.attr,
748 &iio_dev_attr_t_sense_hyst_value.dev_attr.attr,
749 &iio_dev_attr_v0_high.dev_attr.attr,
750 &iio_dev_attr_v0_low.dev_attr.attr,
751 &iio_dev_attr_v0_hyst.dev_attr.attr,
752 &iio_dev_attr_v1_high.dev_attr.attr,
753 &iio_dev_attr_v1_low.dev_attr.attr,
754 &iio_dev_attr_v1_hyst.dev_attr.attr,
755 &iio_dev_attr_v2_high.dev_attr.attr,
756 &iio_dev_attr_v2_low.dev_attr.attr,
757 &iio_dev_attr_v2_hyst.dev_attr.attr,
758 &iio_dev_attr_v3_high.dev_attr.attr,
759 &iio_dev_attr_v3_low.dev_attr.attr,
760 &iio_dev_attr_v3_hyst.dev_attr.attr,
761 &iio_dev_attr_v4_high.dev_attr.attr,
762 &iio_dev_attr_v4_low.dev_attr.attr,
763 &iio_dev_attr_v4_hyst.dev_attr.attr,
764 &iio_dev_attr_v5_high.dev_attr.attr,
765 &iio_dev_attr_v5_low.dev_attr.attr,
766 &iio_dev_attr_v5_hyst.dev_attr.attr,
767 &iio_dev_attr_v6_high.dev_attr.attr,
768 &iio_dev_attr_v6_low.dev_attr.attr,
769 &iio_dev_attr_v6_hyst.dev_attr.attr,
770 &iio_dev_attr_v7_high.dev_attr.attr,
771 &iio_dev_attr_v7_low.dev_attr.attr,
772 &iio_dev_attr_v7_hyst.dev_attr.attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400773 NULL,
774};
775
776static struct attribute_group ad7291_event_attribute_group = {
777 .attrs = ad7291_event_attributes,
778};
779
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100780static const struct iio_info ad7291_info = {
781 .attrs = &ad7291_attribute_group,
782 .num_interrupt_lines = 1,
783 .event_attrs = &ad7291_event_attribute_group,
784};
785
Sonic Zhangddaecd52010-10-27 21:43:55 -0400786/*
787 * device probe and remove
788 */
789
790static int __devinit ad7291_probe(struct i2c_client *client,
791 const struct i2c_device_id *id)
792{
793 struct ad7291_chip_info *chip;
Jonathan Camerond4397972011-06-27 13:07:23 +0100794 struct iio_dev *indio_dev;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400795 int ret = 0;
796
Jonathan Camerond4397972011-06-27 13:07:23 +0100797 indio_dev = iio_allocate_device(sizeof(*chip));
798 if (indio_dev == NULL) {
799 ret = -ENOMEM;
800 goto error_ret;
801 }
Dan Carpenter03bda052011-06-29 22:50:48 +0300802 chip = iio_priv(indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400803 /* this is only used for device removal purposes */
Jonathan Camerond4397972011-06-27 13:07:23 +0100804 i2c_set_clientdata(client, indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400805
806 chip->client = client;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400807 chip->command = AD7291_NOISE_DELAY | AD7291_T_SENSE_MASK;
808
Jonathan Camerond4397972011-06-27 13:07:23 +0100809 indio_dev->name = id->name;
810 indio_dev->dev.parent = &client->dev;
811 indio_dev->info = &ad7291_info;
812 indio_dev->modes = INDIO_DIRECT_MODE;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400813
Jonathan Camerond4397972011-06-27 13:07:23 +0100814 ret = iio_device_register(indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400815 if (ret)
816 goto error_free_dev;
817
818 if (client->irq > 0) {
Jonathan Cameron58c03232011-05-18 14:41:11 +0100819 ret = request_threaded_irq(client->irq,
820 NULL,
821 &ad7291_event_handler,
822 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
Jonathan Cameron845bd122011-05-18 14:41:44 +0100823 id->name,
Jonathan Camerond4397972011-06-27 13:07:23 +0100824 indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400825 if (ret)
826 goto error_unreg_dev;
827
Sonic Zhangddaecd52010-10-27 21:43:55 -0400828 /* set irq polarity low level */
829 chip->command |= AD7291_ALART_POLARITY;
830 }
831
832 ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command);
833 if (ret) {
834 ret = -EIO;
835 goto error_unreg_irq;
836 }
837
838 dev_info(&client->dev, "%s temperature sensor registered.\n",
839 id->name);
840
841 return 0;
842
843error_unreg_irq:
Jonathan Camerond4397972011-06-27 13:07:23 +0100844 free_irq(client->irq, indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400845error_unreg_dev:
Jonathan Camerond4397972011-06-27 13:07:23 +0100846 iio_device_unregister(indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400847error_free_dev:
Jonathan Camerond4397972011-06-27 13:07:23 +0100848 iio_free_device(indio_dev);
849error_ret:
Sonic Zhangddaecd52010-10-27 21:43:55 -0400850 return ret;
851}
852
853static int __devexit ad7291_remove(struct i2c_client *client)
854{
Jonathan Camerond4397972011-06-27 13:07:23 +0100855 struct iio_dev *indio_dev = i2c_get_clientdata(client);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400856
857 if (client->irq)
Jonathan Camerond4397972011-06-27 13:07:23 +0100858 free_irq(client->irq, indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400859 iio_device_unregister(indio_dev);
Jonathan Camerond4397972011-06-27 13:07:23 +0100860 iio_free_device(indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400861
862 return 0;
863}
864
865static const struct i2c_device_id ad7291_id[] = {
866 { "ad7291", 0 },
867 {}
868};
869
870MODULE_DEVICE_TABLE(i2c, ad7291_id);
871
872static struct i2c_driver ad7291_driver = {
873 .driver = {
874 .name = "ad7291",
875 },
876 .probe = ad7291_probe,
877 .remove = __devexit_p(ad7291_remove),
878 .id_table = ad7291_id,
879};
880
881static __init int ad7291_init(void)
882{
883 return i2c_add_driver(&ad7291_driver);
884}
885
886static __exit void ad7291_exit(void)
887{
888 i2c_del_driver(&ad7291_driver);
889}
890
891MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
892MODULE_DESCRIPTION("Analog Devices AD7291 digital"
893 " temperature sensor driver");
894MODULE_LICENSE("GPL v2");
895
896module_init(ad7291_init);
897module_exit(ad7291_exit);