blob: 23ad18ec320621df6a3eb21220814ee7db7ab3d9 [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 {
63 const char *name;
64 struct i2c_client *client;
65 struct iio_dev *indio_dev;
Sonic Zhangddaecd52010-10-27 21:43:55 -040066 u16 command;
67 u8 channels; /* Active voltage channels */
68};
69
70/*
71 * struct ad7291_chip_info - chip specifc information
72 */
73
74struct ad7291_limit_regs {
75 u16 data_high;
76 u16 data_low;
77 u16 hysteresis;
78};
79
80/*
81 * ad7291 register access by I2C
82 */
83static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
84{
85 struct i2c_client *client = chip->client;
86 int ret = 0;
87
88 ret = i2c_smbus_read_word_data(client, reg);
89 if (ret < 0) {
90 dev_err(&client->dev, "I2C read error\n");
91 return ret;
92 }
93
94 *data = swab16((u16)ret);
95
96 return 0;
97}
98
99static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
100{
101 struct i2c_client *client = chip->client;
102 int ret = 0;
103
104 ret = i2c_smbus_write_word_data(client, reg, swab16(data));
105 if (ret < 0)
106 dev_err(&client->dev, "I2C write error\n");
107
108 return ret;
109}
110
111/* Returns negative errno, or else the number of words read. */
112static int ad7291_i2c_read_data(struct ad7291_chip_info *chip, u8 reg, u16 *data)
113{
114 struct i2c_client *client = chip->client;
115 u8 commands[4];
116 int ret = 0;
117 int i, count;
118
119 if (reg == AD7291_T_SENSE || reg == AD7291_T_AVERAGE)
120 count = 2;
121 else if (reg == AD7291_VOLTAGE) {
122 if (!chip->channels) {
123 dev_err(&client->dev, "No voltage channel is selected.\n");
124 return -EINVAL;
125 }
126 count = 2 + chip->channels * 2;
127 } else {
128 dev_err(&client->dev, "I2C wrong data register\n");
129 return -EINVAL;
130 }
131
132 commands[0] = 0;
133 commands[1] = (chip->command >> 8) & 0xff;
134 commands[2] = chip->command & 0xff;
135 commands[3] = reg;
136
137 ret = i2c_master_send(client, commands, 4);
138 if (ret < 0) {
139 dev_err(&client->dev, "I2C master send error\n");
140 return ret;
141 }
142
143 ret = i2c_master_recv(client, (u8 *)data, count);
144 if (ret < 0) {
145 dev_err(&client->dev, "I2C master receive error\n");
146 return ret;
147 }
148 ret >>= 2;
149
150 for (i = 0; i < ret; i++)
151 data[i] = swab16(data[i]);
152
153 return ret;
154}
155
156static ssize_t ad7291_show_mode(struct device *dev,
157 struct device_attribute *attr,
158 char *buf)
159{
160 struct iio_dev *dev_info = dev_get_drvdata(dev);
161 struct ad7291_chip_info *chip = dev_info->dev_data;
162
163 if (chip->command & AD7291_AUTOCYCLE)
164 return sprintf(buf, "autocycle\n");
165 else
166 return sprintf(buf, "command\n");
167}
168
169static ssize_t ad7291_store_mode(struct device *dev,
170 struct device_attribute *attr,
171 const char *buf,
172 size_t len)
173{
174 struct iio_dev *dev_info = dev_get_drvdata(dev);
175 struct ad7291_chip_info *chip = dev_info->dev_data;
176 u16 command;
177 int ret;
178
179 command = chip->command & (~AD7291_AUTOCYCLE);
180 if (strcmp(buf, "autocycle"))
181 command |= AD7291_AUTOCYCLE;
182
183 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
184 if (ret)
185 return -EIO;
186
187 chip->command = command;
188
189 return ret;
190}
191
192static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
193 ad7291_show_mode,
194 ad7291_store_mode,
195 0);
196
197static ssize_t ad7291_show_available_modes(struct device *dev,
198 struct device_attribute *attr,
199 char *buf)
200{
201 return sprintf(buf, "command\nautocycle\n");
202}
203
204static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7291_show_available_modes, NULL, 0);
205
206static ssize_t ad7291_store_reset(struct device *dev,
207 struct device_attribute *attr,
208 const char *buf,
209 size_t len)
210{
211 struct iio_dev *dev_info = dev_get_drvdata(dev);
212 struct ad7291_chip_info *chip = dev_info->dev_data;
213 u16 command;
214 int ret;
215
216 command = chip->command | AD7291_RESET;
217
218 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
219 if (ret)
220 return -EIO;
221
222 return ret;
223}
224
225static IIO_DEVICE_ATTR(reset, S_IWUSR,
226 NULL,
227 ad7291_store_reset,
228 0);
229
230static ssize_t ad7291_show_ext_ref(struct device *dev,
231 struct device_attribute *attr,
232 char *buf)
233{
234 struct iio_dev *dev_info = dev_get_drvdata(dev);
235 struct ad7291_chip_info *chip = dev_info->dev_data;
236
237 return sprintf(buf, "%d\n", !!(chip->command & AD7291_EXT_REF));
238}
239
240static ssize_t ad7291_store_ext_ref(struct device *dev,
241 struct device_attribute *attr,
242 const char *buf,
243 size_t len)
244{
245 struct iio_dev *dev_info = dev_get_drvdata(dev);
246 struct ad7291_chip_info *chip = dev_info->dev_data;
247 u16 command;
248 int ret;
249
250 command = chip->command & (~AD7291_EXT_REF);
251 if (strcmp(buf, "1"))
252 command |= AD7291_EXT_REF;
253
254 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
255 if (ret)
256 return -EIO;
257
258 chip->command = command;
259
260 return ret;
261}
262
263static IIO_DEVICE_ATTR(ext_ref, S_IRUGO | S_IWUSR,
264 ad7291_show_ext_ref,
265 ad7291_store_ext_ref,
266 0);
267
268static ssize_t ad7291_show_noise_delay(struct device *dev,
269 struct device_attribute *attr,
270 char *buf)
271{
272 struct iio_dev *dev_info = dev_get_drvdata(dev);
273 struct ad7291_chip_info *chip = dev_info->dev_data;
274
275 return sprintf(buf, "%d\n", !!(chip->command & AD7291_NOISE_DELAY));
276}
277
278static ssize_t ad7291_store_noise_delay(struct device *dev,
279 struct device_attribute *attr,
280 const char *buf,
281 size_t len)
282{
283 struct iio_dev *dev_info = dev_get_drvdata(dev);
284 struct ad7291_chip_info *chip = dev_info->dev_data;
285 u16 command;
286 int ret;
287
288 command = chip->command & (~AD7291_NOISE_DELAY);
289 if (strcmp(buf, "1"))
290 command |= AD7291_NOISE_DELAY;
291
292 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
293 if (ret)
294 return -EIO;
295
296 chip->command = command;
297
298 return ret;
299}
300
301static IIO_DEVICE_ATTR(noise_delay, S_IRUGO | S_IWUSR,
302 ad7291_show_noise_delay,
303 ad7291_store_noise_delay,
304 0);
305
306static ssize_t ad7291_show_t_sense(struct device *dev,
307 struct device_attribute *attr,
308 char *buf)
309{
310 struct iio_dev *dev_info = dev_get_drvdata(dev);
311 struct ad7291_chip_info *chip = dev_info->dev_data;
312 u16 data;
313 char sign = ' ';
314 int ret;
315
316 ret = ad7291_i2c_read_data(chip, AD7291_T_SENSE, &data);
317 if (ret)
318 return -EIO;
319
320 if (data & AD7291_T_VALUE_SIGN) {
321 /* convert supplement to positive value */
322 data = (AD7291_T_VALUE_SIGN << 1) - data;
323 sign = '-';
324 }
325
326 return sprintf(buf, "%c%d.%.2d\n", sign,
327 (data >> AD7291_T_VALUE_FLOAT_OFFSET),
328 (data & AD7291_T_VALUE_FLOAT_MASK) * 25);
329}
330
331static IIO_DEVICE_ATTR(t_sense, S_IRUGO, ad7291_show_t_sense, NULL, 0);
332
333static ssize_t ad7291_show_t_average(struct device *dev,
334 struct device_attribute *attr,
335 char *buf)
336{
337 struct iio_dev *dev_info = dev_get_drvdata(dev);
338 struct ad7291_chip_info *chip = dev_info->dev_data;
339 u16 data;
340 char sign = ' ';
341 int ret;
342
343 ret = ad7291_i2c_read_data(chip, AD7291_T_AVERAGE, &data);
344 if (ret)
345 return -EIO;
346
347 if (data & AD7291_T_VALUE_SIGN) {
348 /* convert supplement to positive value */
349 data = (AD7291_T_VALUE_SIGN << 1) - data;
350 sign = '-';
351 }
352
353 return sprintf(buf, "%c%d.%.2d\n", sign,
354 (data >> AD7291_T_VALUE_FLOAT_OFFSET),
355 (data & AD7291_T_VALUE_FLOAT_MASK) * 25);
356}
357
358static IIO_DEVICE_ATTR(t_average, S_IRUGO, ad7291_show_t_average, NULL, 0);
359
360static ssize_t ad7291_show_voltage(struct device *dev,
361 struct device_attribute *attr,
362 char *buf)
363{
364 struct iio_dev *dev_info = dev_get_drvdata(dev);
365 struct ad7291_chip_info *chip = dev_info->dev_data;
366 u16 data[AD7291_VOLTAGE_LIMIT_COUNT];
367 int i, size, ret;
368
369 ret = ad7291_i2c_read_data(chip, AD7291_VOLTAGE, data);
370 if (ret)
371 return -EIO;
372
373 for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
374 if (chip->command & (AD7291_T_SENSE_MASK << i)) {
375 ret = sprintf(buf, "channel[%d]=%d\n", i,
376 data[i] & AD7291_VALUE_MASK);
377 if (ret < 0)
378 break;
379 buf += ret;
380 size += ret;
381 }
382 }
383
384 return size;
385}
386
387static IIO_DEVICE_ATTR(voltage, S_IRUGO, ad7291_show_voltage, NULL, 0);
388
389static ssize_t ad7291_show_channel_mask(struct device *dev,
390 struct device_attribute *attr,
391 char *buf)
392{
393 struct iio_dev *dev_info = dev_get_drvdata(dev);
394 struct ad7291_chip_info *chip = dev_info->dev_data;
395
396 return sprintf(buf, "0x%x\n", (chip->command & AD7291_VOLTAGE_MASK) >>
397 AD7291_VOLTAGE_OFFSET);
398}
399
400static ssize_t ad7291_store_channel_mask(struct device *dev,
401 struct device_attribute *attr,
402 const char *buf,
403 size_t len)
404{
405 struct iio_dev *dev_info = dev_get_drvdata(dev);
406 struct ad7291_chip_info *chip = dev_info->dev_data;
407 u16 command;
408 unsigned long data;
409 int i, ret;
410
411 ret = strict_strtoul(buf, 16, &data);
412 if (ret || data > 0xff)
413 return -EINVAL;
414
415 command = chip->command & (~AD7291_VOLTAGE_MASK);
416 command |= data << AD7291_VOLTAGE_OFFSET;
417
418 ret = ad7291_i2c_write(chip, AD7291_COMMAND, command);
419 if (ret)
420 return -EIO;
421
422 chip->command = command;
423
424 for (i = 0, chip->channels = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
425 if (chip->command & (AD7291_T_SENSE_MASK << i))
426 chip->channels++;
427 }
428
429 return ret;
430}
431
432static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR,
433 ad7291_show_channel_mask,
434 ad7291_store_channel_mask,
435 0);
436
437static ssize_t ad7291_show_name(struct device *dev,
438 struct device_attribute *attr,
439 char *buf)
440{
441 struct iio_dev *dev_info = dev_get_drvdata(dev);
442 struct ad7291_chip_info *chip = dev_info->dev_data;
443 return sprintf(buf, "%s\n", chip->name);
444}
445
446static IIO_DEVICE_ATTR(name, S_IRUGO, ad7291_show_name, NULL, 0);
447
448static struct attribute *ad7291_attributes[] = {
449 &iio_dev_attr_available_modes.dev_attr.attr,
450 &iio_dev_attr_mode.dev_attr.attr,
451 &iio_dev_attr_reset.dev_attr.attr,
452 &iio_dev_attr_ext_ref.dev_attr.attr,
453 &iio_dev_attr_noise_delay.dev_attr.attr,
454 &iio_dev_attr_t_sense.dev_attr.attr,
455 &iio_dev_attr_t_average.dev_attr.attr,
456 &iio_dev_attr_voltage.dev_attr.attr,
457 &iio_dev_attr_channel_mask.dev_attr.attr,
458 &iio_dev_attr_name.dev_attr.attr,
459 NULL,
460};
461
462static const struct attribute_group ad7291_attribute_group = {
463 .attrs = ad7291_attributes,
464};
465
466/*
467 * temperature bound events
468 */
469
470#define IIO_EVENT_CODE_AD7291_T_SENSE_HIGH IIO_BUFFER_EVENT_CODE(0)
471#define IIO_EVENT_CODE_AD7291_T_SENSE_LOW IIO_BUFFER_EVENT_CODE(1)
472#define IIO_EVENT_CODE_AD7291_T_AVG_HIGH IIO_BUFFER_EVENT_CODE(2)
473#define IIO_EVENT_CODE_AD7291_T_AVG_LOW IIO_BUFFER_EVENT_CODE(3)
474#define IIO_EVENT_CODE_AD7291_VOLTAGE_BASE IIO_BUFFER_EVENT_CODE(4)
475
Jonathan Cameron58c03232011-05-18 14:41:11 +0100476static irqreturn_t ad7291_event_handler(int irq, void *private)
Sonic Zhangddaecd52010-10-27 21:43:55 -0400477{
Jonathan Cameron58c03232011-05-18 14:41:11 +0100478 struct iio_dev *indio_dev = private;
479 struct ad7291_chip_info *chip = iio_dev_get_devdata(private);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400480 u16 t_status, v_status;
481 u16 command;
482 int i;
Jonathan Cameron58c03232011-05-18 14:41:11 +0100483 s64 timestamp = iio_get_time_ns();
Sonic Zhangddaecd52010-10-27 21:43:55 -0400484
485 if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100486 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400487
488 if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100489 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400490
491 if (!(t_status || v_status))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100492 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400493
494 command = chip->command | AD7291_ALART_CLEAR;
495 ad7291_i2c_write(chip, AD7291_COMMAND, command);
496
497 command = chip->command & ~AD7291_ALART_CLEAR;
498 ad7291_i2c_write(chip, AD7291_COMMAND, command);
499
Sonic Zhangddaecd52010-10-27 21:43:55 -0400500 for (i = 0; i < 4; i++) {
501 if (t_status & (1 << i))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100502 iio_push_event(indio_dev, 0,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400503 IIO_EVENT_CODE_AD7291_T_SENSE_HIGH + i,
Jonathan Cameron58c03232011-05-18 14:41:11 +0100504 timestamp);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400505 }
506
507 for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i++) {
508 if (v_status & (1 << i))
Jonathan Cameron58c03232011-05-18 14:41:11 +0100509 iio_push_event(indio_dev, 0,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400510 IIO_EVENT_CODE_AD7291_VOLTAGE_BASE + i,
Jonathan Cameron58c03232011-05-18 14:41:11 +0100511 timestamp);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400512 }
Jonathan Cameron58c03232011-05-18 14:41:11 +0100513
514 return IRQ_HANDLED;
Sonic Zhangddaecd52010-10-27 21:43:55 -0400515}
516
Sonic Zhangddaecd52010-10-27 21:43:55 -0400517static inline ssize_t ad7291_show_t_bound(struct device *dev,
518 struct device_attribute *attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400519 char *buf)
520{
521 struct iio_dev *dev_info = dev_get_drvdata(dev);
522 struct ad7291_chip_info *chip = dev_info->dev_data;
Jonathan Cameron58c03232011-05-18 14:41:11 +0100523 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400524 u16 data;
525 char sign = ' ';
526 int ret;
527
Jonathan Cameron58c03232011-05-18 14:41:11 +0100528 ret = ad7291_i2c_read(chip, this_attr->address, &data);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400529 if (ret)
530 return -EIO;
531
532 data &= AD7291_VALUE_MASK;
533 if (data & AD7291_T_VALUE_SIGN) {
534 /* convert supplement to positive value */
535 data = (AD7291_T_VALUE_SIGN << 1) - data;
536 sign = '-';
537 }
538
539 return sprintf(buf, "%c%d.%.2d\n", sign,
540 data >> AD7291_T_VALUE_FLOAT_OFFSET,
541 (data & AD7291_T_VALUE_FLOAT_MASK) * 25);
542}
543
544static inline ssize_t ad7291_set_t_bound(struct device *dev,
545 struct device_attribute *attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400546 const char *buf,
547 size_t len)
548{
549 struct iio_dev *dev_info = dev_get_drvdata(dev);
550 struct ad7291_chip_info *chip = dev_info->dev_data;
Jonathan Cameron58c03232011-05-18 14:41:11 +0100551 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400552 long tmp1, tmp2;
553 u16 data;
554 char *pos;
555 int ret;
556
557 pos = strchr(buf, '.');
558
559 ret = strict_strtol(buf, 10, &tmp1);
560
561 if (ret || tmp1 > 127 || tmp1 < -128)
562 return -EINVAL;
563
564 if (pos) {
565 len = strlen(pos);
566 if (len > AD7291_T_VALUE_FLOAT_OFFSET)
567 len = AD7291_T_VALUE_FLOAT_OFFSET;
568 pos[len] = 0;
569 ret = strict_strtol(pos, 10, &tmp2);
570
571 if (!ret)
572 tmp2 = (tmp2 / 25) * 25;
573 }
574
575 if (tmp1 < 0)
576 data = (u16)(-tmp1);
577 else
578 data = (u16)tmp1;
579 data = (data << AD7291_T_VALUE_FLOAT_OFFSET) |
580 (tmp2 & AD7291_T_VALUE_FLOAT_MASK);
581 if (tmp1 < 0)
582 /* convert positive value to supplyment */
583 data = (AD7291_T_VALUE_SIGN << 1) - data;
584
Jonathan Cameron58c03232011-05-18 14:41:11 +0100585 ret = ad7291_i2c_write(chip, this_attr->address, data);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400586 if (ret)
587 return -EIO;
588
589 return ret;
590}
591
Sonic Zhangddaecd52010-10-27 21:43:55 -0400592static inline ssize_t ad7291_show_v_bound(struct device *dev,
593 struct device_attribute *attr,
594 u8 bound_reg,
595 char *buf)
596{
597 struct iio_dev *dev_info = dev_get_drvdata(dev);
598 struct ad7291_chip_info *chip = dev_info->dev_data;
599 u16 data;
600 int ret;
601
602 if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE ||
603 bound_reg >= AD7291_VOLTAGE_LIMIT_BASE +
604 AD7291_VOLTAGE_LIMIT_COUNT)
605 return -EINVAL;
606
607 ret = ad7291_i2c_read(chip, bound_reg, &data);
608 if (ret)
609 return -EIO;
610
611 data &= AD7291_VALUE_MASK;
612
613 return sprintf(buf, "%d\n", data);
614}
615
616static inline ssize_t ad7291_set_v_bound(struct device *dev,
617 struct device_attribute *attr,
618 u8 bound_reg,
619 const char *buf,
620 size_t len)
621{
622 struct iio_dev *dev_info = dev_get_drvdata(dev);
623 struct ad7291_chip_info *chip = dev_info->dev_data;
624 unsigned long value;
625 u16 data;
626 int ret;
627
628 if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE ||
629 bound_reg >= AD7291_VOLTAGE_LIMIT_BASE +
630 AD7291_VOLTAGE_LIMIT_COUNT)
631 return -EINVAL;
632
633 ret = strict_strtoul(buf, 10, &value);
634
635 if (ret || value >= 4096)
636 return -EINVAL;
637
638 data = (u16)value;
639 ret = ad7291_i2c_write(chip, bound_reg, data);
640 if (ret)
641 return -EIO;
642
643 return ret;
644}
645
Jonathan Cameron58c03232011-05-18 14:41:11 +0100646static IIO_DEVICE_ATTR(t_sense_high_value,
647 S_IRUGO | S_IWUSR,
648 ad7291_show_t_bound, ad7291_set_t_bound,
649 AD7291_T_SENSE_HIGH);
650static IIO_DEVICE_ATTR(t_sense_low_value,
651 S_IRUGO | S_IWUSR,
652 ad7291_show_t_bound, ad7291_set_t_bound,
653 AD7291_T_SENSE_LOW);
654static IIO_DEVICE_ATTR(t_sense_hyst_value,
655 S_IRUGO | S_IWUSR,
656 ad7291_show_t_bound, ad7291_set_t_bound,
657 AD7291_T_SENSE_HYST);
658static IIO_DEVICE_ATTR(v0_high,
659 S_IRUGO | S_IWUSR,
660 ad7291_show_t_bound, ad7291_set_t_bound, 0x04);
661static IIO_DEVICE_ATTR(v0_low,
662 S_IRUGO | S_IWUSR,
663 ad7291_show_t_bound, ad7291_set_t_bound, 0x05);
664static IIO_DEVICE_ATTR(v0_hyst,
665 S_IRUGO | S_IWUSR,
666 ad7291_show_t_bound, ad7291_set_t_bound, 0x06);
667static IIO_DEVICE_ATTR(v1_high,
668 S_IRUGO | S_IWUSR,
669 ad7291_show_t_bound, ad7291_set_t_bound, 0x07);
670static IIO_DEVICE_ATTR(v1_low,
671 S_IRUGO | S_IWUSR,
672 ad7291_show_t_bound, ad7291_set_t_bound, 0x08);
673static IIO_DEVICE_ATTR(v1_hyst,
674 S_IRUGO | S_IWUSR,
675 ad7291_show_t_bound, ad7291_set_t_bound, 0x09);
676static IIO_DEVICE_ATTR(v2_high,
677 S_IRUGO | S_IWUSR,
678 ad7291_show_t_bound, ad7291_set_t_bound, 0x0A);
679static IIO_DEVICE_ATTR(v2_low,
680 S_IRUGO | S_IWUSR,
681 ad7291_show_t_bound, ad7291_set_t_bound, 0x0B);
682static IIO_DEVICE_ATTR(v2_hyst,
683 S_IRUGO | S_IWUSR,
684 ad7291_show_t_bound, ad7291_set_t_bound, 0x0C);
685static IIO_DEVICE_ATTR(v3_high,
686 S_IRUGO | S_IWUSR,
687 /* Datasheet suggests this one and this one only
688 has the registers in different order */
689 ad7291_show_t_bound, ad7291_set_t_bound, 0x0E);
690static IIO_DEVICE_ATTR(v3_low,
691 S_IRUGO | S_IWUSR,
692 ad7291_show_t_bound, ad7291_set_t_bound, 0x0D);
693static IIO_DEVICE_ATTR(v3_hyst,
694 S_IRUGO | S_IWUSR,
695 ad7291_show_t_bound, ad7291_set_t_bound, 0x0F);
696static IIO_DEVICE_ATTR(v4_high,
697 S_IRUGO | S_IWUSR,
698 ad7291_show_t_bound, ad7291_set_t_bound, 0x10);
699static IIO_DEVICE_ATTR(v4_low,
700 S_IRUGO | S_IWUSR,
701 ad7291_show_t_bound, ad7291_set_t_bound, 0x11);
702static IIO_DEVICE_ATTR(v4_hyst,
703 S_IRUGO | S_IWUSR,
704 ad7291_show_t_bound, ad7291_set_t_bound, 0x12);
705static IIO_DEVICE_ATTR(v5_high,
706 S_IRUGO | S_IWUSR,
707 ad7291_show_t_bound, ad7291_set_t_bound, 0x13);
708static IIO_DEVICE_ATTR(v5_low,
709 S_IRUGO | S_IWUSR,
710 ad7291_show_t_bound, ad7291_set_t_bound, 0x14);
711static IIO_DEVICE_ATTR(v5_hyst,
712 S_IRUGO | S_IWUSR,
713 ad7291_show_t_bound, ad7291_set_t_bound, 0x15);
714static IIO_DEVICE_ATTR(v6_high,
715 S_IRUGO | S_IWUSR,
716 ad7291_show_t_bound, ad7291_set_t_bound, 0x16);
717static IIO_DEVICE_ATTR(v6_low,
718 S_IRUGO | S_IWUSR,
719 ad7291_show_t_bound, ad7291_set_t_bound, 0x17);
720static IIO_DEVICE_ATTR(v6_hyst,
721 S_IRUGO | S_IWUSR,
722 ad7291_show_t_bound, ad7291_set_t_bound, 0x18);
723static IIO_DEVICE_ATTR(v7_high,
724 S_IRUGO | S_IWUSR,
725 ad7291_show_t_bound, ad7291_set_t_bound, 0x19);
726static IIO_DEVICE_ATTR(v7_low,
727 S_IRUGO | S_IWUSR,
728 ad7291_show_t_bound, ad7291_set_t_bound, 0x1A);
729static IIO_DEVICE_ATTR(v7_hyst,
730 S_IRUGO | S_IWUSR,
731 ad7291_show_t_bound, ad7291_set_t_bound, 0x1B);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400732
733static struct attribute *ad7291_event_attributes[] = {
Jonathan Cameron58c03232011-05-18 14:41:11 +0100734 &iio_dev_attr_t_sense_high_value.dev_attr.attr,
735 &iio_dev_attr_t_sense_low_value.dev_attr.attr,
736 &iio_dev_attr_t_sense_hyst_value.dev_attr.attr,
737 &iio_dev_attr_v0_high.dev_attr.attr,
738 &iio_dev_attr_v0_low.dev_attr.attr,
739 &iio_dev_attr_v0_hyst.dev_attr.attr,
740 &iio_dev_attr_v1_high.dev_attr.attr,
741 &iio_dev_attr_v1_low.dev_attr.attr,
742 &iio_dev_attr_v1_hyst.dev_attr.attr,
743 &iio_dev_attr_v2_high.dev_attr.attr,
744 &iio_dev_attr_v2_low.dev_attr.attr,
745 &iio_dev_attr_v2_hyst.dev_attr.attr,
746 &iio_dev_attr_v3_high.dev_attr.attr,
747 &iio_dev_attr_v3_low.dev_attr.attr,
748 &iio_dev_attr_v3_hyst.dev_attr.attr,
749 &iio_dev_attr_v4_high.dev_attr.attr,
750 &iio_dev_attr_v4_low.dev_attr.attr,
751 &iio_dev_attr_v4_hyst.dev_attr.attr,
752 &iio_dev_attr_v5_high.dev_attr.attr,
753 &iio_dev_attr_v5_low.dev_attr.attr,
754 &iio_dev_attr_v5_hyst.dev_attr.attr,
755 &iio_dev_attr_v6_high.dev_attr.attr,
756 &iio_dev_attr_v6_low.dev_attr.attr,
757 &iio_dev_attr_v6_hyst.dev_attr.attr,
758 &iio_dev_attr_v7_high.dev_attr.attr,
759 &iio_dev_attr_v7_low.dev_attr.attr,
760 &iio_dev_attr_v7_hyst.dev_attr.attr,
Sonic Zhangddaecd52010-10-27 21:43:55 -0400761 NULL,
762};
763
764static struct attribute_group ad7291_event_attribute_group = {
765 .attrs = ad7291_event_attributes,
766};
767
768/*
769 * device probe and remove
770 */
771
772static int __devinit ad7291_probe(struct i2c_client *client,
773 const struct i2c_device_id *id)
774{
775 struct ad7291_chip_info *chip;
776 int ret = 0;
777
778 chip = kzalloc(sizeof(struct ad7291_chip_info), GFP_KERNEL);
779
780 if (chip == NULL)
781 return -ENOMEM;
782
783 /* this is only used for device removal purposes */
784 i2c_set_clientdata(client, chip);
785
786 chip->client = client;
787 chip->name = id->name;
788 chip->command = AD7291_NOISE_DELAY | AD7291_T_SENSE_MASK;
789
Jonathan Cameron6f7c8ee2011-04-15 18:55:56 +0100790 chip->indio_dev = iio_allocate_device(0);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400791 if (chip->indio_dev == NULL) {
792 ret = -ENOMEM;
793 goto error_free_chip;
794 }
795
796 chip->indio_dev->dev.parent = &client->dev;
797 chip->indio_dev->attrs = &ad7291_attribute_group;
798 chip->indio_dev->event_attrs = &ad7291_event_attribute_group;
799 chip->indio_dev->dev_data = (void *)chip;
800 chip->indio_dev->driver_module = THIS_MODULE;
801 chip->indio_dev->num_interrupt_lines = 1;
802 chip->indio_dev->modes = INDIO_DIRECT_MODE;
803
804 ret = iio_device_register(chip->indio_dev);
805 if (ret)
806 goto error_free_dev;
807
808 if (client->irq > 0) {
Jonathan Cameron58c03232011-05-18 14:41:11 +0100809 ret = request_threaded_irq(client->irq,
810 NULL,
811 &ad7291_event_handler,
812 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
813 chip->name,
814 chip->indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400815 if (ret)
816 goto error_unreg_dev;
817
Sonic Zhangddaecd52010-10-27 21:43:55 -0400818 /* set irq polarity low level */
819 chip->command |= AD7291_ALART_POLARITY;
820 }
821
822 ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command);
823 if (ret) {
824 ret = -EIO;
825 goto error_unreg_irq;
826 }
827
828 dev_info(&client->dev, "%s temperature sensor registered.\n",
829 id->name);
830
831 return 0;
832
833error_unreg_irq:
Jonathan Cameron58c03232011-05-18 14:41:11 +0100834 free_irq(client->irq, chip->indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400835error_unreg_dev:
836 iio_device_unregister(chip->indio_dev);
837error_free_dev:
838 iio_free_device(chip->indio_dev);
839error_free_chip:
840 kfree(chip);
841
842 return ret;
843}
844
845static int __devexit ad7291_remove(struct i2c_client *client)
846{
847 struct ad7291_chip_info *chip = i2c_get_clientdata(client);
848 struct iio_dev *indio_dev = chip->indio_dev;
849
850 if (client->irq)
Jonathan Cameron58c03232011-05-18 14:41:11 +0100851 free_irq(client->irq, chip->indio_dev);
Sonic Zhangddaecd52010-10-27 21:43:55 -0400852 iio_device_unregister(indio_dev);
853 iio_free_device(chip->indio_dev);
854 kfree(chip);
855
856 return 0;
857}
858
859static const struct i2c_device_id ad7291_id[] = {
860 { "ad7291", 0 },
861 {}
862};
863
864MODULE_DEVICE_TABLE(i2c, ad7291_id);
865
866static struct i2c_driver ad7291_driver = {
867 .driver = {
868 .name = "ad7291",
869 },
870 .probe = ad7291_probe,
871 .remove = __devexit_p(ad7291_remove),
872 .id_table = ad7291_id,
873};
874
875static __init int ad7291_init(void)
876{
877 return i2c_add_driver(&ad7291_driver);
878}
879
880static __exit void ad7291_exit(void)
881{
882 i2c_del_driver(&ad7291_driver);
883}
884
885MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
886MODULE_DESCRIPTION("Analog Devices AD7291 digital"
887 " temperature sensor driver");
888MODULE_LICENSE("GPL v2");
889
890module_init(ad7291_init);
891module_exit(ad7291_exit);