blob: 13c39292d3f2fbb5ebad81a3ca023168d0aee152 [file] [log] [blame]
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001/*
2 * ADT7316 digital temperature sensor driver supporting ADT7316/7/8 ADT7516/7/9
3 *
4 *
5 * Copyright 2010 Analog Devices Inc.
6 *
7 * Licensed under the GPL-2 or later.
8 */
9
10#include <linux/interrupt.h>
11#include <linux/gpio.h>
12#include <linux/workqueue.h>
13#include <linux/device.h>
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/sysfs.h>
17#include <linux/list.h>
18#include <linux/i2c.h>
19#include <linux/rtc.h>
Paul Gortmaker99c97852011-07-03 15:49:50 -040020#include <linux/module.h>
Sonic Zhang35f6b6b2010-10-27 21:43:52 -040021
22#include "../iio.h"
Jonathan Cameronaf5046a2011-10-26 17:41:32 +010023#include "../events.h"
Sonic Zhang35f6b6b2010-10-27 21:43:52 -040024#include "../sysfs.h"
25#include "adt7316.h"
26
27/*
28 * ADT7316 registers definition
29 */
30#define ADT7316_INT_STAT1 0x0
31#define ADT7316_INT_STAT2 0x1
32#define ADT7316_LSB_IN_TEMP_VDD 0x3
33#define ADT7316_LSB_IN_TEMP_MASK 0x3
34#define ADT7316_LSB_VDD_MASK 0xC
35#define ADT7316_LSB_VDD_OFFSET 2
36#define ADT7316_LSB_EX_TEMP_AIN 0x4
37#define ADT7316_LSB_EX_TEMP_MASK 0x3
38#define ADT7516_LSB_AIN_SHIFT 2
39#define ADT7316_AD_MSB_DATA_BASE 0x6
40#define ADT7316_AD_MSB_DATA_REGS 3
41#define ADT7516_AD_MSB_DATA_REGS 6
42#define ADT7316_MSB_VDD 0x6
43#define ADT7316_MSB_IN_TEMP 0x7
44#define ADT7316_MSB_EX_TEMP 0x8
45#define ADT7516_MSB_AIN1 0x8
46#define ADT7516_MSB_AIN2 0x9
47#define ADT7516_MSB_AIN3 0xA
48#define ADT7516_MSB_AIN4 0xB
49#define ADT7316_DA_DATA_BASE 0x10
50#define ADT7316_DA_MSB_DATA_REGS 4
51#define ADT7316_LSB_DAC_A 0x10
52#define ADT7316_MSB_DAC_A 0x11
53#define ADT7316_LSB_DAC_B 0x12
54#define ADT7316_MSB_DAC_B 0x13
55#define ADT7316_LSB_DAC_C 0x14
56#define ADT7316_MSB_DAC_C 0x15
57#define ADT7316_LSB_DAC_D 0x16
58#define ADT7316_MSB_DAC_D 0x17
59#define ADT7316_CONFIG1 0x18
60#define ADT7316_CONFIG2 0x19
61#define ADT7316_CONFIG3 0x1A
62#define ADT7316_LDAC_CONFIG 0x1B
63#define ADT7316_DAC_CONFIG 0x1C
64#define ADT7316_INT_MASK1 0x1D
65#define ADT7316_INT_MASK2 0x1E
66#define ADT7316_IN_TEMP_OFFSET 0x1F
67#define ADT7316_EX_TEMP_OFFSET 0x20
68#define ADT7316_IN_ANALOG_TEMP_OFFSET 0x21
69#define ADT7316_EX_ANALOG_TEMP_OFFSET 0x22
70#define ADT7316_VDD_HIGH 0x23
71#define ADT7316_VDD_LOW 0x24
72#define ADT7316_IN_TEMP_HIGH 0x25
73#define ADT7316_IN_TEMP_LOW 0x26
74#define ADT7316_EX_TEMP_HIGH 0x27
75#define ADT7316_EX_TEMP_LOW 0x28
76#define ADT7516_AIN2_HIGH 0x2B
77#define ADT7516_AIN2_LOW 0x2C
78#define ADT7516_AIN3_HIGH 0x2D
79#define ADT7516_AIN3_LOW 0x2E
80#define ADT7516_AIN4_HIGH 0x2F
81#define ADT7516_AIN4_LOW 0x30
82#define ADT7316_DEVICE_ID 0x4D
83#define ADT7316_MANUFACTURE_ID 0x4E
84#define ADT7316_DEVICE_REV 0x4F
85#define ADT7316_SPI_LOCK_STAT 0x7F
86
87/*
88 * ADT7316 config1
89 */
90#define ADT7316_EN 0x1
91#define ADT7516_SEL_EX_TEMP 0x4
92#define ADT7516_SEL_AIN1_2_EX_TEMP_MASK 0x6
93#define ADT7516_SEL_AIN3 0x8
94#define ADT7316_INT_EN 0x20
95#define ADT7316_INT_POLARITY 0x40
96#define ADT7316_PD 0x80
97
98/*
99 * ADT7316 config2
100 */
101#define ADT7316_AD_SINGLE_CH_MASK 0x3
102#define ADT7516_AD_SINGLE_CH_MASK 0x7
103#define ADT7316_AD_SINGLE_CH_VDD 0
104#define ADT7316_AD_SINGLE_CH_IN 1
105#define ADT7316_AD_SINGLE_CH_EX 2
106#define ADT7516_AD_SINGLE_CH_AIN1 2
107#define ADT7516_AD_SINGLE_CH_AIN2 3
108#define ADT7516_AD_SINGLE_CH_AIN3 4
109#define ADT7516_AD_SINGLE_CH_AIN4 5
110#define ADT7316_AD_SINGLE_CH_MODE 0x10
111#define ADT7316_DISABLE_AVERAGING 0x20
112#define ADT7316_EN_SMBUS_TIMEOUT 0x40
113#define ADT7316_RESET 0x80
114
115/*
116 * ADT7316 config3
117 */
118#define ADT7316_ADCLK_22_5 0x1
119#define ADT7316_DA_HIGH_RESOLUTION 0x2
120#define ADT7316_DA_EN_VIA_DAC_LDCA 0x4
121#define ADT7516_AIN_IN_VREF 0x10
122#define ADT7316_EN_IN_TEMP_PROP_DACA 0x20
123#define ADT7316_EN_EX_TEMP_PROP_DACB 0x40
124
125/*
126 * ADT7316 DAC config
127 */
128#define ADT7316_DA_2VREF_CH_MASK 0xF
129#define ADT7316_DA_EN_MODE_MASK 0x30
130#define ADT7316_DA_EN_MODE_SINGLE 0x00
131#define ADT7316_DA_EN_MODE_AB_CD 0x10
132#define ADT7316_DA_EN_MODE_ABCD 0x20
133#define ADT7316_DA_EN_MODE_LDAC 0x30
134#define ADT7316_VREF_BYPASS_DAC_AB 0x40
135#define ADT7316_VREF_BYPASS_DAC_CD 0x80
136
137/*
138 * ADT7316 LDAC config
139 */
140#define ADT7316_LDAC_EN_DA_MASK 0xF
141#define ADT7316_DAC_IN_VREF 0x10
142#define ADT7516_DAC_AB_IN_VREF 0x10
143#define ADT7516_DAC_CD_IN_VREF 0x20
144#define ADT7516_DAC_IN_VREF_OFFSET 4
145#define ADT7516_DAC_IN_VREF_MASK 0x30
146
147/*
148 * ADT7316 INT_MASK2
149 */
150#define ADT7316_INT_MASK2_VDD 0x10
151
152/*
153 * ADT7316 value masks
154 */
155#define ADT7316_VALUE_MASK 0xfff
156#define ADT7316_T_VALUE_SIGN 0x400
157#define ADT7316_T_VALUE_FLOAT_OFFSET 2
158#define ADT7316_T_VALUE_FLOAT_MASK 0x2
159
160/*
161 * Chip ID
162 */
163#define ID_ADT7316 0x1
164#define ID_ADT7317 0x2
165#define ID_ADT7318 0x3
166#define ID_ADT7516 0x11
167#define ID_ADT7517 0x12
168#define ID_ADT7519 0x14
169
170#define ID_FAMILY_MASK 0xF0
171#define ID_ADT73XX 0x0
172#define ID_ADT75XX 0x10
173
174/*
175 * struct adt7316_chip_info - chip specifc information
176 */
177
178struct adt7316_chip_info {
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400179 struct adt7316_bus bus;
180 u16 ldac_pin;
181 u16 int_mask; /* 0x2f */
182 u8 config1;
183 u8 config2;
184 u8 config3;
185 u8 dac_config; /* DAC config */
186 u8 ldac_config; /* LDAC config */
187 u8 dac_bits; /* 8, 10, 12 */
188 u8 id; /* chip id */
189};
190
191/*
192 * Logic interrupt mask for user application to enable
193 * interrupts.
194 */
195#define ADT7316_IN_TEMP_HIGH_INT_MASK 0x1
196#define ADT7316_IN_TEMP_LOW_INT_MASK 0x2
197#define ADT7316_EX_TEMP_HIGH_INT_MASK 0x4
198#define ADT7316_EX_TEMP_LOW_INT_MASK 0x8
199#define ADT7316_EX_TEMP_FAULT_INT_MASK 0x10
200#define ADT7516_AIN1_INT_MASK 0x4
201#define ADT7516_AIN2_INT_MASK 0x20
202#define ADT7516_AIN3_INT_MASK 0x40
203#define ADT7516_AIN4_INT_MASK 0x80
204#define ADT7316_VDD_INT_MASK 0x100
205#define ADT7316_TEMP_INT_MASK 0x1F
206#define ADT7516_AIN_INT_MASK 0xE0
207#define ADT7316_TEMP_AIN_INT_MASK \
Jonathan Cameron8df32232011-08-12 16:55:32 +0100208 (ADT7316_TEMP_INT_MASK)
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400209
210/*
211 * struct adt7316_chip_info - chip specifc information
212 */
213
214struct adt7316_limit_regs {
215 u16 data_high;
216 u16 data_low;
217};
218
219static ssize_t adt7316_show_enabled(struct device *dev,
220 struct device_attribute *attr,
221 char *buf)
222{
223 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100224 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400225
226 return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN));
227}
228
229static ssize_t _adt7316_store_enabled(struct adt7316_chip_info *chip,
230 int enable)
231{
232 u8 config1;
233 int ret;
234
235 if (enable)
236 config1 = chip->config1 | ADT7316_EN;
237 else
238 config1 = chip->config1 & ~ADT7316_EN;
239
240 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1);
241 if (ret)
242 return -EIO;
243
244 chip->config1 = config1;
245
246 return ret;
247
248}
249
250static ssize_t adt7316_store_enabled(struct device *dev,
251 struct device_attribute *attr,
252 const char *buf,
253 size_t len)
254{
255 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100256 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400257 int enable;
258
259 if (!memcmp(buf, "1", 1))
260 enable = 1;
261 else
262 enable = 0;
263
264 if (_adt7316_store_enabled(chip, enable) < 0)
265 return -EIO;
266 else
267 return len;
268}
269
270static IIO_DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR,
271 adt7316_show_enabled,
272 adt7316_store_enabled,
273 0);
274
275static ssize_t adt7316_show_select_ex_temp(struct device *dev,
276 struct device_attribute *attr,
277 char *buf)
278{
279 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100280 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400281
282 if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
283 return -EPERM;
284
285 return sprintf(buf, "%d\n", !!(chip->config1 & ADT7516_SEL_EX_TEMP));
286}
287
288static ssize_t adt7316_store_select_ex_temp(struct device *dev,
289 struct device_attribute *attr,
290 const char *buf,
291 size_t len)
292{
293 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100294 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400295 u8 config1;
296 int ret;
297
298 if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
299 return -EPERM;
300
301 config1 = chip->config1 & (~ADT7516_SEL_EX_TEMP);
302 if (!memcmp(buf, "1", 1))
303 config1 |= ADT7516_SEL_EX_TEMP;
304
305 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1);
306 if (ret)
307 return -EIO;
308
309 chip->config1 = config1;
310
311 return len;
312}
313
314static IIO_DEVICE_ATTR(select_ex_temp, S_IRUGO | S_IWUSR,
315 adt7316_show_select_ex_temp,
316 adt7316_store_select_ex_temp,
317 0);
318
319static ssize_t adt7316_show_mode(struct device *dev,
320 struct device_attribute *attr,
321 char *buf)
322{
323 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100324 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400325
326 if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE)
327 return sprintf(buf, "single_channel\n");
328 else
329 return sprintf(buf, "round_robin\n");
330}
331
332static ssize_t adt7316_store_mode(struct device *dev,
333 struct device_attribute *attr,
334 const char *buf,
335 size_t len)
336{
337 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100338 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400339 u8 config2;
340 int ret;
341
342 config2 = chip->config2 & (~ADT7316_AD_SINGLE_CH_MODE);
343 if (!memcmp(buf, "single_channel", 14))
344 config2 |= ADT7316_AD_SINGLE_CH_MODE;
345
346 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
347 if (ret)
348 return -EIO;
349
350 chip->config2 = config2;
351
352 return len;
353}
354
355static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
356 adt7316_show_mode,
357 adt7316_store_mode,
358 0);
359
360static ssize_t adt7316_show_all_modes(struct device *dev,
361 struct device_attribute *attr,
362 char *buf)
363{
364 return sprintf(buf, "single_channel\nround_robin\n");
365}
366
367static IIO_DEVICE_ATTR(all_modes, S_IRUGO, adt7316_show_all_modes, NULL, 0);
368
369static ssize_t adt7316_show_ad_channel(struct device *dev,
370 struct device_attribute *attr,
371 char *buf)
372{
373 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100374 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400375
376 if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
377 return -EPERM;
378
379 switch (chip->config2 & ADT7516_AD_SINGLE_CH_MASK) {
380 case ADT7316_AD_SINGLE_CH_VDD:
381 return sprintf(buf, "0 - VDD\n");
382 case ADT7316_AD_SINGLE_CH_IN:
383 return sprintf(buf, "1 - Internal Temperature\n");
384 case ADT7316_AD_SINGLE_CH_EX:
385 if (((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) &&
386 (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0)
387 return sprintf(buf, "2 - AIN1\n");
388 else
389 return sprintf(buf, "2 - External Temperature\n");
390 case ADT7516_AD_SINGLE_CH_AIN2:
391 if ((chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0)
392 return sprintf(buf, "3 - AIN2\n");
393 else
394 return sprintf(buf, "N/A\n");
395 case ADT7516_AD_SINGLE_CH_AIN3:
396 if (chip->config1 & ADT7516_SEL_AIN3)
397 return sprintf(buf, "4 - AIN3\n");
398 else
399 return sprintf(buf, "N/A\n");
400 case ADT7516_AD_SINGLE_CH_AIN4:
401 return sprintf(buf, "5 - AIN4\n");
402 default:
403 return sprintf(buf, "N/A\n");
Joe Perches95cd17c2011-04-10 14:31:35 -0700404 }
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400405}
406
407static ssize_t adt7316_store_ad_channel(struct device *dev,
408 struct device_attribute *attr,
409 const char *buf,
410 size_t len)
411{
412 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100413 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400414 u8 config2;
415 unsigned long data = 0;
416 int ret;
417
418 if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
419 return -EPERM;
420
421 ret = strict_strtoul(buf, 10, &data);
422 if (ret)
423 return -EINVAL;
424
425 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) {
426 if (data > 5)
427 return -EINVAL;
428
429 config2 = chip->config2 & (~ADT7516_AD_SINGLE_CH_MASK);
430 } else {
431 if (data > 2)
432 return -EINVAL;
433
434 config2 = chip->config2 & (~ADT7316_AD_SINGLE_CH_MASK);
435 }
436
437
438 config2 |= data;
439
440 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
441 if (ret)
442 return -EIO;
443
444 chip->config2 = config2;
445
446 return len;
447}
448
449static IIO_DEVICE_ATTR(ad_channel, S_IRUGO | S_IWUSR,
450 adt7316_show_ad_channel,
451 adt7316_store_ad_channel,
452 0);
453
454static ssize_t adt7316_show_all_ad_channels(struct device *dev,
455 struct device_attribute *attr,
456 char *buf)
457{
458 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100459 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400460
461 if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
462 return -EPERM;
463
464 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
465 return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n"
Jonathan Cameron383f6502011-05-18 14:42:18 +0100466 "2 - External Temperature or AIN1\n"
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400467 "3 - AIN2\n4 - AIN3\n5 - AIN4\n");
468 else
469 return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n"
470 "2 - External Temperature\n");
471}
472
473static IIO_DEVICE_ATTR(all_ad_channels, S_IRUGO,
474 adt7316_show_all_ad_channels, NULL, 0);
475
476static ssize_t adt7316_show_disable_averaging(struct device *dev,
477 struct device_attribute *attr,
478 char *buf)
479{
480 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100481 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400482
483 return sprintf(buf, "%d\n",
484 !!(chip->config2 & ADT7316_DISABLE_AVERAGING));
485}
486
487static ssize_t adt7316_store_disable_averaging(struct device *dev,
488 struct device_attribute *attr,
489 const char *buf,
490 size_t len)
491{
492 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100493 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400494 u8 config2;
495 int ret;
496
497 config2 = chip->config2 & (~ADT7316_DISABLE_AVERAGING);
498 if (!memcmp(buf, "1", 1))
499 config2 |= ADT7316_DISABLE_AVERAGING;
500
501 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
502 if (ret)
503 return -EIO;
504
505 chip->config2 = config2;
506
507 return len;
508}
509
510static IIO_DEVICE_ATTR(disable_averaging, S_IRUGO | S_IWUSR,
511 adt7316_show_disable_averaging,
512 adt7316_store_disable_averaging,
513 0);
514
515static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev,
516 struct device_attribute *attr,
517 char *buf)
518{
519 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100520 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400521
522 return sprintf(buf, "%d\n",
523 !!(chip->config2 & ADT7316_EN_SMBUS_TIMEOUT));
524}
525
526static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev,
527 struct device_attribute *attr,
528 const char *buf,
529 size_t len)
530{
531 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100532 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400533 u8 config2;
534 int ret;
535
536 config2 = chip->config2 & (~ADT7316_EN_SMBUS_TIMEOUT);
537 if (!memcmp(buf, "1", 1))
538 config2 |= ADT7316_EN_SMBUS_TIMEOUT;
539
540 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
541 if (ret)
542 return -EIO;
543
544 chip->config2 = config2;
545
546 return len;
547}
548
549static IIO_DEVICE_ATTR(enable_smbus_timeout, S_IRUGO | S_IWUSR,
550 adt7316_show_enable_smbus_timeout,
551 adt7316_store_enable_smbus_timeout,
552 0);
553
554
555static ssize_t adt7316_store_reset(struct device *dev,
556 struct device_attribute *attr,
557 const char *buf,
558 size_t len)
559{
560 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100561 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400562 u8 config2;
563 int ret;
564
565 config2 = chip->config2 | ADT7316_RESET;
566
567 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2);
568 if (ret)
569 return -EIO;
570
571 return len;
572}
573
574static IIO_DEVICE_ATTR(reset, S_IWUSR,
575 NULL,
576 adt7316_store_reset,
577 0);
578
579static ssize_t adt7316_show_powerdown(struct device *dev,
580 struct device_attribute *attr,
581 char *buf)
582{
583 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100584 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400585
586 return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD));
587}
588
589static ssize_t adt7316_store_powerdown(struct device *dev,
590 struct device_attribute *attr,
591 const char *buf,
592 size_t len)
593{
594 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100595 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400596 u8 config1;
597 int ret;
598
599 config1 = chip->config1 & (~ADT7316_PD);
600 if (!memcmp(buf, "1", 1))
601 config1 |= ADT7316_PD;
602
603 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1);
604 if (ret)
605 return -EIO;
606
607 chip->config1 = config1;
608
609 return len;
610}
611
612static IIO_DEVICE_ATTR(powerdown, S_IRUGO | S_IWUSR,
613 adt7316_show_powerdown,
614 adt7316_store_powerdown,
615 0);
616
617static ssize_t adt7316_show_fast_ad_clock(struct device *dev,
618 struct device_attribute *attr,
619 char *buf)
620{
621 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100622 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400623
624 return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5));
625}
626
627static ssize_t adt7316_store_fast_ad_clock(struct device *dev,
628 struct device_attribute *attr,
629 const char *buf,
630 size_t len)
631{
632 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100633 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400634 u8 config3;
635 int ret;
636
637 config3 = chip->config3 & (~ADT7316_ADCLK_22_5);
638 if (!memcmp(buf, "1", 1))
639 config3 |= ADT7316_ADCLK_22_5;
640
641 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3);
642 if (ret)
643 return -EIO;
644
645 chip->config3 = config3;
646
647 return len;
648}
649
650static IIO_DEVICE_ATTR(fast_ad_clock, S_IRUGO | S_IWUSR,
651 adt7316_show_fast_ad_clock,
652 adt7316_store_fast_ad_clock,
653 0);
654
655static ssize_t adt7316_show_da_high_resolution(struct device *dev,
656 struct device_attribute *attr,
657 char *buf)
658{
659 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100660 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400661
662 if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) {
663 if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
664 return sprintf(buf, "1 (12 bits)\n");
665 else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517)
666 return sprintf(buf, "1 (10 bits)\n");
667 }
668
669 return sprintf(buf, "0 (8 bits)\n");
670}
671
672static ssize_t adt7316_store_da_high_resolution(struct device *dev,
673 struct device_attribute *attr,
674 const char *buf,
675 size_t len)
676{
677 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100678 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400679 u8 config3;
680 int ret;
681
682 chip->dac_bits = 8;
683
684 if (!memcmp(buf, "1", 1)) {
685 config3 = chip->config3 | ADT7316_DA_HIGH_RESOLUTION;
686 if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516)
687 chip->dac_bits = 12;
688 else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517)
689 chip->dac_bits = 10;
690 } else
691 config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION);
692
693 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3);
694 if (ret)
695 return -EIO;
696
697 chip->config3 = config3;
698
699 return len;
700}
701
702static IIO_DEVICE_ATTR(da_high_resolution, S_IRUGO | S_IWUSR,
703 adt7316_show_da_high_resolution,
704 adt7316_store_da_high_resolution,
705 0);
706
707static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev,
708 struct device_attribute *attr,
709 char *buf)
710{
711 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100712 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400713
714 if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
715 return -EPERM;
716
717 return sprintf(buf, "%d\n",
718 !!(chip->config3 & ADT7516_AIN_IN_VREF));
719}
720
721static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev,
722 struct device_attribute *attr,
723 const char *buf,
724 size_t len)
725{
726 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100727 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400728 u8 config3;
729 int ret;
730
731 if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
732 return -EPERM;
733
734 if (memcmp(buf, "1", 1))
735 config3 = chip->config3 & (~ADT7516_AIN_IN_VREF);
736 else
737 config3 = chip->config3 | ADT7516_AIN_IN_VREF;
738
739 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3);
740 if (ret)
741 return -EIO;
742
743 chip->config3 = config3;
744
745 return len;
746}
747
748static IIO_DEVICE_ATTR(AIN_internal_Vref, S_IRUGO | S_IWUSR,
749 adt7316_show_AIN_internal_Vref,
750 adt7316_store_AIN_internal_Vref,
751 0);
752
753
754static ssize_t adt7316_show_enable_prop_DACA(struct device *dev,
755 struct device_attribute *attr,
756 char *buf)
757{
758 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100759 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400760
761 return sprintf(buf, "%d\n",
762 !!(chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA));
763}
764
765static ssize_t adt7316_store_enable_prop_DACA(struct device *dev,
766 struct device_attribute *attr,
767 const char *buf,
768 size_t len)
769{
770 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100771 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400772 u8 config3;
773 int ret;
774
775 config3 = chip->config3 & (~ADT7316_EN_IN_TEMP_PROP_DACA);
776 if (!memcmp(buf, "1", 1))
777 config3 |= ADT7316_EN_IN_TEMP_PROP_DACA;
778
779 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3);
780 if (ret)
781 return -EIO;
782
783 chip->config3 = config3;
784
785 return len;
786}
787
788static IIO_DEVICE_ATTR(enable_proportion_DACA, S_IRUGO | S_IWUSR,
789 adt7316_show_enable_prop_DACA,
790 adt7316_store_enable_prop_DACA,
791 0);
792
793static ssize_t adt7316_show_enable_prop_DACB(struct device *dev,
794 struct device_attribute *attr,
795 char *buf)
796{
797 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100798 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400799
800 return sprintf(buf, "%d\n",
801 !!(chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB));
802}
803
804static ssize_t adt7316_store_enable_prop_DACB(struct device *dev,
805 struct device_attribute *attr,
806 const char *buf,
807 size_t len)
808{
809 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100810 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400811 u8 config3;
812 int ret;
813
814 config3 = chip->config3 & (~ADT7316_EN_EX_TEMP_PROP_DACB);
815 if (!memcmp(buf, "1", 1))
816 config3 |= ADT7316_EN_EX_TEMP_PROP_DACB;
817
818 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3);
819 if (ret)
820 return -EIO;
821
822 chip->config3 = config3;
823
824 return len;
825}
826
827static IIO_DEVICE_ATTR(enable_proportion_DACB, S_IRUGO | S_IWUSR,
828 adt7316_show_enable_prop_DACB,
829 adt7316_store_enable_prop_DACB,
830 0);
831
832static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev,
833 struct device_attribute *attr,
834 char *buf)
835{
836 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100837 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400838
839 return sprintf(buf, "0x%x\n",
840 chip->dac_config & ADT7316_DA_2VREF_CH_MASK);
841}
842
843static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
844 struct device_attribute *attr,
845 const char *buf,
846 size_t len)
847{
848 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100849 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400850 u8 dac_config;
851 unsigned long data = 0;
852 int ret;
853
854 ret = strict_strtoul(buf, 16, &data);
855 if (ret || data > ADT7316_DA_2VREF_CH_MASK)
856 return -EINVAL;
857
858 dac_config = chip->dac_config & (~ADT7316_DA_2VREF_CH_MASK);
859 dac_config |= data;
860
861 ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config);
862 if (ret)
863 return -EIO;
864
865 chip->dac_config = dac_config;
866
867 return len;
868}
869
870static IIO_DEVICE_ATTR(DAC_2Vref_channels_mask, S_IRUGO | S_IWUSR,
871 adt7316_show_DAC_2Vref_ch_mask,
872 adt7316_store_DAC_2Vref_ch_mask,
873 0);
874
875static ssize_t adt7316_show_DAC_update_mode(struct device *dev,
876 struct device_attribute *attr,
877 char *buf)
878{
879 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100880 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400881
882 if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
883 return sprintf(buf, "manual\n");
884 else {
885 switch (chip->dac_config & ADT7316_DA_EN_MODE_MASK) {
886 case ADT7316_DA_EN_MODE_SINGLE:
887 return sprintf(buf, "0 - auto at any MSB DAC writing\n");
888 case ADT7316_DA_EN_MODE_AB_CD:
889 return sprintf(buf, "1 - auto at MSB DAC AB and CD writing\n");
890 case ADT7316_DA_EN_MODE_ABCD:
891 return sprintf(buf, "2 - auto at MSB DAC ABCD writing\n");
892 default: /* ADT7316_DA_EN_MODE_LDAC */
893 return sprintf(buf, "3 - manual\n");
Joe Perches95cd17c2011-04-10 14:31:35 -0700894 }
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400895 }
896}
897
898static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
899 struct device_attribute *attr,
900 const char *buf,
901 size_t len)
902{
903 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100904 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400905 u8 dac_config;
906 unsigned long data;
907 int ret;
908
909 if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
910 return -EPERM;
911
912 ret = strict_strtoul(buf, 10, &data);
913 if (ret || data > ADT7316_DA_EN_MODE_MASK)
914 return -EINVAL;
915
916 dac_config = chip->dac_config & (~ADT7316_DA_EN_MODE_MASK);
917 dac_config |= data;
918
919 ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config);
920 if (ret)
921 return -EIO;
922
923 chip->dac_config = dac_config;
924
925 return len;
926}
927
928static IIO_DEVICE_ATTR(DAC_update_mode, S_IRUGO | S_IWUSR,
929 adt7316_show_DAC_update_mode,
930 adt7316_store_DAC_update_mode,
931 0);
932
933static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
934 struct device_attribute *attr,
935 char *buf)
936{
937 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100938 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400939
940 if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)
941 return sprintf(buf, "0 - auto at any MSB DAC writing\n"
942 "1 - auto at MSB DAC AB and CD writing\n"
943 "2 - auto at MSB DAC ABCD writing\n"
944 "3 - manual\n");
945 else
946 return sprintf(buf, "manual\n");
947}
948
949static IIO_DEVICE_ATTR(all_DAC_update_modes, S_IRUGO,
950 adt7316_show_all_DAC_update_modes, NULL, 0);
951
952
953static ssize_t adt7316_store_update_DAC(struct device *dev,
954 struct device_attribute *attr,
955 const char *buf,
956 size_t len)
957{
958 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100959 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400960 u8 ldac_config;
961 unsigned long data;
962 int ret;
963
964 if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) {
965 if ((chip->dac_config & ADT7316_DA_EN_MODE_MASK) !=
966 ADT7316_DA_EN_MODE_LDAC)
967 return -EPERM;
968
969 ret = strict_strtoul(buf, 16, &data);
970 if (ret || data > ADT7316_LDAC_EN_DA_MASK)
971 return -EINVAL;
972
973 ldac_config = chip->ldac_config & (~ADT7316_LDAC_EN_DA_MASK);
974 ldac_config |= data;
975
976 ret = chip->bus.write(chip->bus.client, ADT7316_LDAC_CONFIG,
977 ldac_config);
978 if (ret)
979 return -EIO;
980 } else {
981 gpio_set_value(chip->ldac_pin, 0);
982 gpio_set_value(chip->ldac_pin, 1);
983 }
984
985 return len;
986}
987
988static IIO_DEVICE_ATTR(update_DAC, S_IRUGO | S_IWUSR,
989 NULL,
990 adt7316_store_update_DAC,
991 0);
992
993static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev,
994 struct device_attribute *attr,
995 char *buf)
996{
997 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +0100998 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -0400999
1000 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
1001 return -EPERM;
1002
1003 return sprintf(buf, "%d\n",
1004 !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_AB));
1005}
1006
1007static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
1008 struct device_attribute *attr,
1009 const char *buf,
1010 size_t len)
1011{
1012 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001013 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001014 u8 dac_config;
1015 int ret;
1016
1017 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
1018 return -EPERM;
1019
1020 dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_AB);
1021 if (!memcmp(buf, "1", 1))
1022 dac_config |= ADT7316_VREF_BYPASS_DAC_AB;
1023
1024 ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config);
1025 if (ret)
1026 return -EIO;
1027
1028 chip->dac_config = dac_config;
1029
1030 return len;
1031}
1032
1033static IIO_DEVICE_ATTR(DA_AB_Vref_bypass, S_IRUGO | S_IWUSR,
1034 adt7316_show_DA_AB_Vref_bypass,
1035 adt7316_store_DA_AB_Vref_bypass,
1036 0);
1037
1038static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev,
1039 struct device_attribute *attr,
1040 char *buf)
1041{
1042 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001043 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001044
1045 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
1046 return -EPERM;
1047
1048 return sprintf(buf, "%d\n",
1049 !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_CD));
1050}
1051
1052static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
1053 struct device_attribute *attr,
1054 const char *buf,
1055 size_t len)
1056{
1057 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001058 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001059 u8 dac_config;
1060 int ret;
1061
1062 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
1063 return -EPERM;
1064
1065 dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_CD);
1066 if (!memcmp(buf, "1", 1))
1067 dac_config |= ADT7316_VREF_BYPASS_DAC_CD;
1068
1069 ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config);
1070 if (ret)
1071 return -EIO;
1072
1073 chip->dac_config = dac_config;
1074
1075 return len;
1076}
1077
1078static IIO_DEVICE_ATTR(DA_CD_Vref_bypass, S_IRUGO | S_IWUSR,
1079 adt7316_show_DA_CD_Vref_bypass,
1080 adt7316_store_DA_CD_Vref_bypass,
1081 0);
1082
1083static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev,
1084 struct device_attribute *attr,
1085 char *buf)
1086{
1087 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001088 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001089
1090 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
1091 return sprintf(buf, "0x%x\n",
1092 (chip->dac_config & ADT7516_DAC_IN_VREF_MASK) >>
1093 ADT7516_DAC_IN_VREF_OFFSET);
1094 else
1095 return sprintf(buf, "%d\n",
1096 !!(chip->dac_config & ADT7316_DAC_IN_VREF));
1097}
1098
1099static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
1100 struct device_attribute *attr,
1101 const char *buf,
1102 size_t len)
1103{
1104 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001105 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001106 u8 ldac_config;
1107 unsigned long data;
1108 int ret;
1109
1110 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) {
1111 ret = strict_strtoul(buf, 16, &data);
1112 if (ret || data > 3)
1113 return -EINVAL;
1114
1115 ldac_config = chip->ldac_config & (~ADT7516_DAC_IN_VREF_MASK);
1116 if (data & 0x1)
1117 ldac_config |= ADT7516_DAC_AB_IN_VREF;
1118 else if (data & 0x2)
1119 ldac_config |= ADT7516_DAC_CD_IN_VREF;
1120 } else {
1121 ret = strict_strtoul(buf, 16, &data);
1122 if (ret)
1123 return -EINVAL;
1124
1125 ldac_config = chip->ldac_config & (~ADT7316_DAC_IN_VREF);
1126 if (data)
1127 ldac_config = chip->ldac_config | ADT7316_DAC_IN_VREF;
1128 }
1129
1130 ret = chip->bus.write(chip->bus.client, ADT7316_LDAC_CONFIG, ldac_config);
1131 if (ret)
1132 return -EIO;
1133
1134 chip->ldac_config = ldac_config;
1135
1136 return len;
1137}
1138
1139static IIO_DEVICE_ATTR(DAC_internal_Vref, S_IRUGO | S_IWUSR,
1140 adt7316_show_DAC_internal_Vref,
1141 adt7316_store_DAC_internal_Vref,
1142 0);
1143
1144static ssize_t adt7316_show_ad(struct adt7316_chip_info *chip,
1145 int channel, char *buf)
1146{
1147 u16 data;
1148 u8 msb, lsb;
1149 char sign = ' ';
1150 int ret;
1151
1152 if ((chip->config2 & ADT7316_AD_SINGLE_CH_MODE) &&
1153 channel != (chip->config2 & ADT7516_AD_SINGLE_CH_MASK))
1154 return -EPERM;
1155
1156 switch (channel) {
1157 case ADT7316_AD_SINGLE_CH_IN:
1158 ret = chip->bus.read(chip->bus.client,
1159 ADT7316_LSB_IN_TEMP_VDD, &lsb);
1160 if (ret)
1161 return -EIO;
1162
1163 ret = chip->bus.read(chip->bus.client,
1164 ADT7316_AD_MSB_DATA_BASE + channel, &msb);
1165 if (ret)
1166 return -EIO;
1167
1168 data = msb << ADT7316_T_VALUE_FLOAT_OFFSET;
1169 data |= lsb & ADT7316_LSB_IN_TEMP_MASK;
1170 break;
1171 case ADT7316_AD_SINGLE_CH_VDD:
1172 ret = chip->bus.read(chip->bus.client,
1173 ADT7316_LSB_IN_TEMP_VDD, &lsb);
1174 if (ret)
1175 return -EIO;
1176
1177 ret = chip->bus.read(chip->bus.client,
1178
1179 ADT7316_AD_MSB_DATA_BASE + channel, &msb);
1180 if (ret)
1181 return -EIO;
1182
1183 data = msb << ADT7316_T_VALUE_FLOAT_OFFSET;
1184 data |= (lsb & ADT7316_LSB_VDD_MASK) >> ADT7316_LSB_VDD_OFFSET;
1185 return sprintf(buf, "%d\n", data);
1186 default: /* ex_temp and ain */
1187 ret = chip->bus.read(chip->bus.client,
1188 ADT7316_LSB_EX_TEMP_AIN, &lsb);
1189 if (ret)
1190 return -EIO;
1191
1192 ret = chip->bus.read(chip->bus.client,
1193 ADT7316_AD_MSB_DATA_BASE + channel, &msb);
1194 if (ret)
1195 return -EIO;
1196
1197 data = msb << ADT7316_T_VALUE_FLOAT_OFFSET;
1198 data |= lsb & (ADT7316_LSB_EX_TEMP_MASK <<
1199 (ADT7516_LSB_AIN_SHIFT * (channel -
1200 (ADT7316_MSB_EX_TEMP - ADT7316_AD_MSB_DATA_BASE))));
1201
1202 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
1203 return sprintf(buf, "%d\n", data);
1204 else
1205 break;
Joe Perches95cd17c2011-04-10 14:31:35 -07001206 }
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001207
1208 if (data & ADT7316_T_VALUE_SIGN) {
1209 /* convert supplement to positive value */
1210 data = (ADT7316_T_VALUE_SIGN << 1) - data;
1211 sign = '-';
1212 }
1213
1214 return sprintf(buf, "%c%d.%.2d\n", sign,
1215 (data >> ADT7316_T_VALUE_FLOAT_OFFSET),
1216 (data & ADT7316_T_VALUE_FLOAT_MASK) * 25);
1217}
1218
1219static ssize_t adt7316_show_VDD(struct device *dev,
1220 struct device_attribute *attr,
1221 char *buf)
1222{
1223 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001224 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001225
1226 return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf);
1227}
1228static IIO_DEVICE_ATTR(VDD, S_IRUGO, adt7316_show_VDD, NULL, 0);
1229
1230static ssize_t adt7316_show_in_temp(struct device *dev,
1231 struct device_attribute *attr,
1232 char *buf)
1233{
1234 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001235 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001236
1237 return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf);
1238}
1239
1240static IIO_DEVICE_ATTR(in_temp, S_IRUGO, adt7316_show_in_temp, NULL, 0);
1241
1242static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
1243 struct device_attribute *attr,
1244 char *buf)
1245{
1246 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001247 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001248
1249 return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf);
1250}
1251
1252static IIO_DEVICE_ATTR(ex_temp_AIN1, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0);
1253static IIO_DEVICE_ATTR(ex_temp, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0);
1254
1255static ssize_t adt7316_show_AIN2(struct device *dev,
1256 struct device_attribute *attr,
1257 char *buf)
1258{
1259 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001260 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001261
1262 return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf);
1263}
1264static IIO_DEVICE_ATTR(AIN2, S_IRUGO, adt7316_show_AIN2, NULL, 0);
1265
1266static ssize_t adt7316_show_AIN3(struct device *dev,
1267 struct device_attribute *attr,
1268 char *buf)
1269{
1270 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001271 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001272
1273 return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf);
1274}
1275static IIO_DEVICE_ATTR(AIN3, S_IRUGO, adt7316_show_AIN3, NULL, 0);
1276
1277static ssize_t adt7316_show_AIN4(struct device *dev,
1278 struct device_attribute *attr,
1279 char *buf)
1280{
1281 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001282 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001283
1284 return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf);
1285}
1286static IIO_DEVICE_ATTR(AIN4, S_IRUGO, adt7316_show_AIN4, NULL, 0);
1287
1288static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip,
1289 int offset_addr, char *buf)
1290{
1291 int data;
1292 u8 val;
1293 int ret;
1294
1295 ret = chip->bus.read(chip->bus.client, offset_addr, &val);
1296 if (ret)
1297 return -EIO;
1298
1299 data = (int)val;
1300 if (val & 0x80)
1301 data -= 256;
1302
1303 return sprintf(buf, "%d\n", data);
1304}
1305
1306static ssize_t adt7316_store_temp_offset(struct adt7316_chip_info *chip,
1307 int offset_addr, const char *buf, size_t len)
1308{
1309 long data;
1310 u8 val;
1311 int ret;
1312
1313 ret = strict_strtol(buf, 10, &data);
1314 if (ret || data > 127 || data < -128)
1315 return -EINVAL;
1316
1317 if (data < 0)
1318 data += 256;
1319
1320 val = (u8)data;
1321
1322 ret = chip->bus.write(chip->bus.client, offset_addr, val);
1323 if (ret)
1324 return -EIO;
1325
1326 return len;
1327}
1328
1329static ssize_t adt7316_show_in_temp_offset(struct device *dev,
1330 struct device_attribute *attr,
1331 char *buf)
1332{
1333 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001334 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001335
1336 return adt7316_show_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf);
1337}
1338
1339static ssize_t adt7316_store_in_temp_offset(struct device *dev,
1340 struct device_attribute *attr,
1341 const char *buf,
1342 size_t len)
1343{
1344 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001345 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001346
1347 return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, len);
1348}
1349
1350static IIO_DEVICE_ATTR(in_temp_offset, S_IRUGO | S_IWUSR,
1351 adt7316_show_in_temp_offset,
1352 adt7316_store_in_temp_offset, 0);
1353
1354static ssize_t adt7316_show_ex_temp_offset(struct device *dev,
1355 struct device_attribute *attr,
1356 char *buf)
1357{
1358 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001359 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001360
1361 return adt7316_show_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf);
1362}
1363
1364static ssize_t adt7316_store_ex_temp_offset(struct device *dev,
1365 struct device_attribute *attr,
1366 const char *buf,
1367 size_t len)
1368{
1369 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001370 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001371
1372 return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, len);
1373}
1374
1375static IIO_DEVICE_ATTR(ex_temp_offset, S_IRUGO | S_IWUSR,
1376 adt7316_show_ex_temp_offset,
1377 adt7316_store_ex_temp_offset, 0);
1378
1379static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev,
1380 struct device_attribute *attr,
1381 char *buf)
1382{
1383 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001384 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001385
1386 return adt7316_show_temp_offset(chip,
1387 ADT7316_IN_ANALOG_TEMP_OFFSET, buf);
1388}
1389
1390static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev,
1391 struct device_attribute *attr,
1392 const char *buf,
1393 size_t len)
1394{
1395 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001396 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001397
1398 return adt7316_store_temp_offset(chip,
1399 ADT7316_IN_ANALOG_TEMP_OFFSET, buf, len);
1400}
1401
1402static IIO_DEVICE_ATTR(in_analog_temp_offset, S_IRUGO | S_IWUSR,
1403 adt7316_show_in_analog_temp_offset,
1404 adt7316_store_in_analog_temp_offset, 0);
1405
1406static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev,
1407 struct device_attribute *attr,
1408 char *buf)
1409{
1410 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001411 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001412
1413 return adt7316_show_temp_offset(chip,
1414 ADT7316_EX_ANALOG_TEMP_OFFSET, buf);
1415}
1416
1417static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev,
1418 struct device_attribute *attr,
1419 const char *buf,
1420 size_t len)
1421{
1422 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001423 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001424
1425 return adt7316_store_temp_offset(chip,
1426 ADT7316_EX_ANALOG_TEMP_OFFSET, buf, len);
1427}
1428
1429static IIO_DEVICE_ATTR(ex_analog_temp_offset, S_IRUGO | S_IWUSR,
1430 adt7316_show_ex_analog_temp_offset,
1431 adt7316_store_ex_analog_temp_offset, 0);
1432
1433static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip,
1434 int channel, char *buf)
1435{
1436 u16 data;
1437 u8 msb, lsb, offset;
1438 int ret;
1439
1440 if (channel >= ADT7316_DA_MSB_DATA_REGS ||
1441 (channel == 0 &&
1442 (chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA)) ||
1443 (channel == 1 &&
1444 (chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB)))
1445 return -EPERM;
1446
1447 offset = chip->dac_bits - 8;
1448
1449 if (chip->dac_bits > 8) {
1450 ret = chip->bus.read(chip->bus.client,
1451 ADT7316_DA_DATA_BASE + channel * 2, &lsb);
1452 if (ret)
1453 return -EIO;
1454 }
1455
1456 ret = chip->bus.read(chip->bus.client,
1457 ADT7316_DA_DATA_BASE + 1 + channel * 2, &msb);
1458 if (ret)
1459 return -EIO;
1460
1461 data = (msb << offset) + (lsb & ((1 << offset) - 1));
1462
1463 return sprintf(buf, "%d\n", data);
1464}
1465
1466static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip,
1467 int channel, const char *buf, size_t len)
1468{
1469 u8 msb, lsb, offset;
1470 unsigned long data;
1471 int ret;
1472
1473 if (channel >= ADT7316_DA_MSB_DATA_REGS ||
1474 (channel == 0 &&
1475 (chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA)) ||
1476 (channel == 1 &&
1477 (chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB)))
1478 return -EPERM;
1479
1480 offset = chip->dac_bits - 8;
1481
1482 ret = strict_strtoul(buf, 10, &data);
1483 if (ret || data >= (1 << chip->dac_bits))
1484 return -EINVAL;
1485
1486 if (chip->dac_bits > 8) {
1487 lsb = data & (1 << offset);
1488 ret = chip->bus.write(chip->bus.client,
1489 ADT7316_DA_DATA_BASE + channel * 2, lsb);
1490 if (ret)
1491 return -EIO;
1492 }
1493
1494 msb = data >> offset;
1495 ret = chip->bus.write(chip->bus.client,
1496 ADT7316_DA_DATA_BASE + 1 + channel * 2, msb);
1497 if (ret)
1498 return -EIO;
1499
1500 return len;
1501}
1502
1503static ssize_t adt7316_show_DAC_A(struct device *dev,
1504 struct device_attribute *attr,
1505 char *buf)
1506{
1507 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001508 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001509
1510 return adt7316_show_DAC(chip, 0, buf);
1511}
1512
1513static ssize_t adt7316_store_DAC_A(struct device *dev,
1514 struct device_attribute *attr,
1515 const char *buf,
1516 size_t len)
1517{
1518 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001519 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001520
1521 return adt7316_store_DAC(chip, 0, buf, len);
1522}
1523
1524static IIO_DEVICE_ATTR(DAC_A, S_IRUGO | S_IWUSR, adt7316_show_DAC_A,
1525 adt7316_store_DAC_A, 0);
1526
1527static ssize_t adt7316_show_DAC_B(struct device *dev,
1528 struct device_attribute *attr,
1529 char *buf)
1530{
1531 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001532 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001533
1534 return adt7316_show_DAC(chip, 1, buf);
1535}
1536
1537static ssize_t adt7316_store_DAC_B(struct device *dev,
1538 struct device_attribute *attr,
1539 const char *buf,
1540 size_t len)
1541{
1542 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001543 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001544
1545 return adt7316_store_DAC(chip, 1, buf, len);
1546}
1547
1548static IIO_DEVICE_ATTR(DAC_B, S_IRUGO | S_IWUSR, adt7316_show_DAC_B,
1549 adt7316_store_DAC_B, 0);
1550
1551static ssize_t adt7316_show_DAC_C(struct device *dev,
1552 struct device_attribute *attr,
1553 char *buf)
1554{
1555 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001556 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001557
1558 return adt7316_show_DAC(chip, 2, buf);
1559}
1560
1561static ssize_t adt7316_store_DAC_C(struct device *dev,
1562 struct device_attribute *attr,
1563 const char *buf,
1564 size_t len)
1565{
1566 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001567 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001568
1569 return adt7316_store_DAC(chip, 2, buf, len);
1570}
1571
1572static IIO_DEVICE_ATTR(DAC_C, S_IRUGO | S_IWUSR, adt7316_show_DAC_C,
1573 adt7316_store_DAC_C, 0);
1574
1575static ssize_t adt7316_show_DAC_D(struct device *dev,
1576 struct device_attribute *attr,
1577 char *buf)
1578{
1579 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001580 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001581
1582 return adt7316_show_DAC(chip, 3, buf);
1583}
1584
1585static ssize_t adt7316_store_DAC_D(struct device *dev,
1586 struct device_attribute *attr,
1587 const char *buf,
1588 size_t len)
1589{
1590 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001591 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001592
1593 return adt7316_store_DAC(chip, 3, buf, len);
1594}
1595
1596static IIO_DEVICE_ATTR(DAC_D, S_IRUGO | S_IWUSR, adt7316_show_DAC_D,
1597 adt7316_store_DAC_D, 0);
1598
1599static ssize_t adt7316_show_device_id(struct device *dev,
1600 struct device_attribute *attr,
1601 char *buf)
1602{
1603 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001604 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001605 u8 id;
1606 int ret;
1607
1608 ret = chip->bus.read(chip->bus.client, ADT7316_DEVICE_ID, &id);
1609 if (ret)
1610 return -EIO;
1611
1612 return sprintf(buf, "%d\n", id);
1613}
1614
1615static IIO_DEVICE_ATTR(device_id, S_IRUGO, adt7316_show_device_id, NULL, 0);
1616
1617static ssize_t adt7316_show_manufactorer_id(struct device *dev,
1618 struct device_attribute *attr,
1619 char *buf)
1620{
1621 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001622 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001623 u8 id;
1624 int ret;
1625
1626 ret = chip->bus.read(chip->bus.client, ADT7316_MANUFACTURE_ID, &id);
1627 if (ret)
1628 return -EIO;
1629
1630 return sprintf(buf, "%d\n", id);
1631}
1632
1633static IIO_DEVICE_ATTR(manufactorer_id, S_IRUGO,
1634 adt7316_show_manufactorer_id, NULL, 0);
1635
1636static ssize_t adt7316_show_device_rev(struct device *dev,
1637 struct device_attribute *attr,
1638 char *buf)
1639{
1640 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001641 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001642 u8 rev;
1643 int ret;
1644
1645 ret = chip->bus.read(chip->bus.client, ADT7316_DEVICE_REV, &rev);
1646 if (ret)
1647 return -EIO;
1648
1649 return sprintf(buf, "%d\n", rev);
1650}
1651
1652static IIO_DEVICE_ATTR(device_rev, S_IRUGO, adt7316_show_device_rev, NULL, 0);
1653
1654static ssize_t adt7316_show_bus_type(struct device *dev,
1655 struct device_attribute *attr,
1656 char *buf)
1657{
1658 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001659 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001660 u8 stat;
1661 int ret;
1662
1663 ret = chip->bus.read(chip->bus.client, ADT7316_SPI_LOCK_STAT, &stat);
1664 if (ret)
1665 return -EIO;
1666
1667 if (stat)
1668 return sprintf(buf, "spi\n");
1669 else
1670 return sprintf(buf, "i2c\n");
1671}
1672
1673static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0);
1674
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001675static struct attribute *adt7316_attributes[] = {
1676 &iio_dev_attr_all_modes.dev_attr.attr,
1677 &iio_dev_attr_mode.dev_attr.attr,
1678 &iio_dev_attr_reset.dev_attr.attr,
1679 &iio_dev_attr_enabled.dev_attr.attr,
1680 &iio_dev_attr_ad_channel.dev_attr.attr,
1681 &iio_dev_attr_all_ad_channels.dev_attr.attr,
1682 &iio_dev_attr_disable_averaging.dev_attr.attr,
1683 &iio_dev_attr_enable_smbus_timeout.dev_attr.attr,
1684 &iio_dev_attr_powerdown.dev_attr.attr,
1685 &iio_dev_attr_fast_ad_clock.dev_attr.attr,
1686 &iio_dev_attr_da_high_resolution.dev_attr.attr,
1687 &iio_dev_attr_enable_proportion_DACA.dev_attr.attr,
1688 &iio_dev_attr_enable_proportion_DACB.dev_attr.attr,
1689 &iio_dev_attr_DAC_2Vref_channels_mask.dev_attr.attr,
1690 &iio_dev_attr_DAC_update_mode.dev_attr.attr,
1691 &iio_dev_attr_all_DAC_update_modes.dev_attr.attr,
1692 &iio_dev_attr_update_DAC.dev_attr.attr,
1693 &iio_dev_attr_DA_AB_Vref_bypass.dev_attr.attr,
1694 &iio_dev_attr_DA_CD_Vref_bypass.dev_attr.attr,
1695 &iio_dev_attr_DAC_internal_Vref.dev_attr.attr,
1696 &iio_dev_attr_VDD.dev_attr.attr,
1697 &iio_dev_attr_in_temp.dev_attr.attr,
1698 &iio_dev_attr_ex_temp.dev_attr.attr,
1699 &iio_dev_attr_in_temp_offset.dev_attr.attr,
1700 &iio_dev_attr_ex_temp_offset.dev_attr.attr,
1701 &iio_dev_attr_in_analog_temp_offset.dev_attr.attr,
1702 &iio_dev_attr_ex_analog_temp_offset.dev_attr.attr,
1703 &iio_dev_attr_DAC_A.dev_attr.attr,
1704 &iio_dev_attr_DAC_B.dev_attr.attr,
1705 &iio_dev_attr_DAC_C.dev_attr.attr,
1706 &iio_dev_attr_DAC_D.dev_attr.attr,
1707 &iio_dev_attr_device_id.dev_attr.attr,
1708 &iio_dev_attr_manufactorer_id.dev_attr.attr,
1709 &iio_dev_attr_device_rev.dev_attr.attr,
1710 &iio_dev_attr_bus_type.dev_attr.attr,
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001711 NULL,
1712};
1713
1714static const struct attribute_group adt7316_attribute_group = {
1715 .attrs = adt7316_attributes,
1716};
1717
1718static struct attribute *adt7516_attributes[] = {
1719 &iio_dev_attr_all_modes.dev_attr.attr,
1720 &iio_dev_attr_mode.dev_attr.attr,
1721 &iio_dev_attr_select_ex_temp.dev_attr.attr,
1722 &iio_dev_attr_reset.dev_attr.attr,
1723 &iio_dev_attr_enabled.dev_attr.attr,
1724 &iio_dev_attr_ad_channel.dev_attr.attr,
1725 &iio_dev_attr_all_ad_channels.dev_attr.attr,
1726 &iio_dev_attr_disable_averaging.dev_attr.attr,
1727 &iio_dev_attr_enable_smbus_timeout.dev_attr.attr,
1728 &iio_dev_attr_powerdown.dev_attr.attr,
1729 &iio_dev_attr_fast_ad_clock.dev_attr.attr,
1730 &iio_dev_attr_AIN_internal_Vref.dev_attr.attr,
1731 &iio_dev_attr_da_high_resolution.dev_attr.attr,
1732 &iio_dev_attr_enable_proportion_DACA.dev_attr.attr,
1733 &iio_dev_attr_enable_proportion_DACB.dev_attr.attr,
1734 &iio_dev_attr_DAC_2Vref_channels_mask.dev_attr.attr,
1735 &iio_dev_attr_DAC_update_mode.dev_attr.attr,
1736 &iio_dev_attr_all_DAC_update_modes.dev_attr.attr,
1737 &iio_dev_attr_update_DAC.dev_attr.attr,
1738 &iio_dev_attr_DA_AB_Vref_bypass.dev_attr.attr,
1739 &iio_dev_attr_DA_CD_Vref_bypass.dev_attr.attr,
1740 &iio_dev_attr_DAC_internal_Vref.dev_attr.attr,
1741 &iio_dev_attr_VDD.dev_attr.attr,
1742 &iio_dev_attr_in_temp.dev_attr.attr,
1743 &iio_dev_attr_ex_temp_AIN1.dev_attr.attr,
1744 &iio_dev_attr_AIN2.dev_attr.attr,
1745 &iio_dev_attr_AIN3.dev_attr.attr,
1746 &iio_dev_attr_AIN4.dev_attr.attr,
1747 &iio_dev_attr_in_temp_offset.dev_attr.attr,
1748 &iio_dev_attr_ex_temp_offset.dev_attr.attr,
1749 &iio_dev_attr_in_analog_temp_offset.dev_attr.attr,
1750 &iio_dev_attr_ex_analog_temp_offset.dev_attr.attr,
1751 &iio_dev_attr_DAC_A.dev_attr.attr,
1752 &iio_dev_attr_DAC_B.dev_attr.attr,
1753 &iio_dev_attr_DAC_C.dev_attr.attr,
1754 &iio_dev_attr_DAC_D.dev_attr.attr,
1755 &iio_dev_attr_device_id.dev_attr.attr,
1756 &iio_dev_attr_manufactorer_id.dev_attr.attr,
1757 &iio_dev_attr_device_rev.dev_attr.attr,
1758 &iio_dev_attr_bus_type.dev_attr.attr,
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001759 NULL,
1760};
1761
1762static const struct attribute_group adt7516_attribute_group = {
1763 .attrs = adt7516_attributes,
1764};
1765
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001766static irqreturn_t adt7316_event_handler(int irq, void *private)
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001767{
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001768 struct iio_dev *indio_dev = private;
Jonathan Cameron70be4292011-06-27 13:07:29 +01001769 struct adt7316_chip_info *chip = iio_priv(indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001770 u8 stat1, stat2;
Jonathan Cameron383f6502011-05-18 14:42:18 +01001771 int ret;
1772 s64 time;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001773
1774 ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT1, &stat1);
1775 if (!ret) {
Jonathan Cameron383f6502011-05-18 14:42:18 +01001776 if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX)
1777 stat1 &= 0x1F;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001778
Jonathan Cameron383f6502011-05-18 14:42:18 +01001779 time = iio_get_time_ns();
1780 if (stat1 & (1 << 0))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001781 iio_push_event(indio_dev,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001782 IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
1783 IIO_EV_TYPE_THRESH,
1784 IIO_EV_DIR_RISING),
1785 time);
1786 if (stat1 & (1 << 1))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001787 iio_push_event(indio_dev,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001788 IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0,
1789 IIO_EV_TYPE_THRESH,
1790 IIO_EV_DIR_FALLING),
1791 time);
1792 if (stat1 & (1 << 2))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001793 iio_push_event(indio_dev,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001794 IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
1795 IIO_EV_TYPE_THRESH,
1796 IIO_EV_DIR_RISING),
1797 time);
1798 if (stat1 & (1 << 3))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001799 iio_push_event(indio_dev,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001800 IIO_UNMOD_EVENT_CODE(IIO_TEMP, 1,
1801 IIO_EV_TYPE_THRESH,
1802 IIO_EV_DIR_FALLING),
1803 time);
1804 if (stat1 & (1 << 5))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001805 iio_push_event(indio_dev,
Jonathan Cameron6835cb62011-09-27 09:56:41 +01001806 IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001807 IIO_EV_TYPE_THRESH,
1808 IIO_EV_DIR_EITHER),
1809 time);
1810 if (stat1 & (1 << 6))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001811 iio_push_event(indio_dev,
Jonathan Cameron6835cb62011-09-27 09:56:41 +01001812 IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 2,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001813 IIO_EV_TYPE_THRESH,
1814 IIO_EV_DIR_EITHER),
1815 time);
1816 if (stat1 & (1 << 7))
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001817 iio_push_event(indio_dev,
Jonathan Cameron6835cb62011-09-27 09:56:41 +01001818 IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 3,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001819 IIO_EV_TYPE_THRESH,
1820 IIO_EV_DIR_EITHER),
1821 time);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001822 }
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001823 ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT2, &stat2);
1824 if (!ret) {
1825 if (stat2 & ADT7316_INT_MASK2_VDD)
Jonathan Cameron5aa96182011-08-30 12:41:06 +01001826 iio_push_event(indio_dev,
Jonathan Cameron6835cb62011-09-27 09:56:41 +01001827 IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
Jonathan Cameron383f6502011-05-18 14:42:18 +01001828 0,
1829 IIO_EV_TYPE_THRESH,
1830 IIO_EV_DIR_RISING),
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001831 iio_get_time_ns());
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001832 }
1833
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001834 return IRQ_HANDLED;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001835}
1836
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001837/*
1838 * Show mask of enabled interrupts in Hex.
1839 */
1840static ssize_t adt7316_show_int_mask(struct device *dev,
1841 struct device_attribute *attr,
1842 char *buf)
1843{
1844 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001845 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001846
1847 return sprintf(buf, "0x%x\n", chip->int_mask);
1848}
1849
1850/*
1851 * Set 1 to the mask in Hex to enabled interrupts.
1852 */
1853static ssize_t adt7316_set_int_mask(struct device *dev,
1854 struct device_attribute *attr,
1855 const char *buf,
1856 size_t len)
1857{
1858 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001859 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001860 unsigned long data;
1861 int ret;
1862 u8 mask;
1863
1864 ret = strict_strtoul(buf, 16, &data);
1865 if (ret || data >= ADT7316_VDD_INT_MASK + 1)
1866 return -EINVAL;
1867
1868 if (data & ADT7316_VDD_INT_MASK)
1869 mask = 0; /* enable vdd int */
1870 else
1871 mask = ADT7316_INT_MASK2_VDD; /* disable vdd int */
1872
1873 ret = chip->bus.write(chip->bus.client, ADT7316_INT_MASK2, mask);
1874 if (!ret) {
1875 chip->int_mask &= ~ADT7316_VDD_INT_MASK;
1876 chip->int_mask |= data & ADT7316_VDD_INT_MASK;
1877 }
1878
1879 if (data & ADT7316_TEMP_AIN_INT_MASK) {
1880 if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX)
1881 /* mask in reg is opposite, set 1 to disable */
1882 mask = (~data) & ADT7316_TEMP_INT_MASK;
1883 else
1884 /* mask in reg is opposite, set 1 to disable */
1885 mask = (~data) & ADT7316_TEMP_AIN_INT_MASK;
1886 }
1887 ret = chip->bus.write(chip->bus.client, ADT7316_INT_MASK1, mask);
1888
1889 chip->int_mask = mask;
1890
1891 return len;
1892}
1893static inline ssize_t adt7316_show_ad_bound(struct device *dev,
1894 struct device_attribute *attr,
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001895 char *buf)
1896{
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001897 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001898 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001899 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001900 u8 val;
1901 int data;
1902 int ret;
1903
1904 if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX &&
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001905 this_attr->address > ADT7316_EX_TEMP_LOW)
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001906 return -EPERM;
1907
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001908 ret = chip->bus.read(chip->bus.client, this_attr->address, &val);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001909 if (ret)
1910 return -EIO;
1911
1912 data = (int)val;
1913
1914 if (!((chip->id & ID_FAMILY_MASK) == ID_ADT75XX &&
1915 (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0)) {
1916 if (data & 0x80)
1917 data -= 256;
1918 }
1919
1920 return sprintf(buf, "%d\n", data);
1921}
1922
1923static inline ssize_t adt7316_set_ad_bound(struct device *dev,
1924 struct device_attribute *attr,
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001925 const char *buf,
1926 size_t len)
1927{
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001928 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001929 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001930 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001931 long data;
1932 u8 val;
1933 int ret;
1934
1935 if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX &&
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001936 this_attr->address > ADT7316_EX_TEMP_LOW)
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001937 return -EPERM;
1938
1939 ret = strict_strtol(buf, 10, &data);
1940 if (ret)
1941 return -EINVAL;
1942
1943 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX &&
1944 (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0) {
1945 if (data > 255 || data < 0)
1946 return -EINVAL;
1947 } else {
1948 if (data > 127 || data < -128)
1949 return -EINVAL;
1950
1951 if (data < 0)
1952 data += 256;
1953 }
1954
1955 val = (u8)data;
1956
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001957 ret = chip->bus.write(chip->bus.client, this_attr->address, val);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001958 if (ret)
1959 return -EIO;
1960
1961 return len;
1962}
1963
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001964static ssize_t adt7316_show_int_enabled(struct device *dev,
1965 struct device_attribute *attr,
1966 char *buf)
1967{
1968 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001969 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001970
1971 return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN));
1972}
1973
1974static ssize_t adt7316_set_int_enabled(struct device *dev,
1975 struct device_attribute *attr,
1976 const char *buf,
1977 size_t len)
1978{
1979 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01001980 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04001981 u8 config1;
1982 int ret;
1983
1984 config1 = chip->config1 & (~ADT7316_INT_EN);
1985 if (!memcmp(buf, "1", 1))
1986 config1 |= ADT7316_INT_EN;
1987
1988 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1);
1989 if (ret)
1990 return -EIO;
1991
1992 chip->config1 = config1;
1993
1994 return len;
1995}
1996
Jonathan Cameron90f79e72011-05-18 14:41:05 +01001997static IIO_DEVICE_ATTR(int_mask,
1998 S_IRUGO | S_IWUSR,
1999 adt7316_show_int_mask, adt7316_set_int_mask,
2000 0);
2001static IIO_DEVICE_ATTR(in_temp_high_value,
2002 S_IRUGO | S_IWUSR,
2003 adt7316_show_ad_bound, adt7316_set_ad_bound,
2004 ADT7316_IN_TEMP_HIGH);
2005static IIO_DEVICE_ATTR(in_temp_low_value,
2006 S_IRUGO | S_IWUSR,
2007 adt7316_show_ad_bound, adt7316_set_ad_bound,
2008 ADT7316_IN_TEMP_LOW);
2009static IIO_DEVICE_ATTR(ex_temp_high_value,
2010 S_IRUGO | S_IWUSR,
2011 adt7316_show_ad_bound, adt7316_set_ad_bound,
2012 ADT7316_EX_TEMP_HIGH);
2013static IIO_DEVICE_ATTR(ex_temp_low_value,
2014 S_IRUGO | S_IWUSR,
2015 adt7316_show_ad_bound, adt7316_set_ad_bound,
2016 ADT7316_EX_TEMP_LOW);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002017
Jonathan Cameron90f79e72011-05-18 14:41:05 +01002018/* NASTY duplication to be fixed */
2019static IIO_DEVICE_ATTR(ex_temp_ain1_high_value,
2020 S_IRUGO | S_IWUSR,
2021 adt7316_show_ad_bound, adt7316_set_ad_bound,
2022 ADT7316_EX_TEMP_HIGH);
2023static IIO_DEVICE_ATTR(ex_temp_ain1_low_value,
2024 S_IRUGO | S_IWUSR,
2025 adt7316_show_ad_bound, adt7316_set_ad_bound,
2026 ADT7316_EX_TEMP_LOW);
2027static IIO_DEVICE_ATTR(ain2_high_value,
2028 S_IRUGO | S_IWUSR,
2029 adt7316_show_ad_bound, adt7316_set_ad_bound,
2030 ADT7516_AIN2_HIGH);
2031static IIO_DEVICE_ATTR(ain2_low_value,
2032 S_IRUGO | S_IWUSR,
2033 adt7316_show_ad_bound, adt7316_set_ad_bound,
2034 ADT7516_AIN2_LOW);
2035static IIO_DEVICE_ATTR(ain3_high_value,
2036 S_IRUGO | S_IWUSR,
2037 adt7316_show_ad_bound, adt7316_set_ad_bound,
2038 ADT7516_AIN3_HIGH);
2039static IIO_DEVICE_ATTR(ain3_low_value,
2040 S_IRUGO | S_IWUSR,
2041 adt7316_show_ad_bound, adt7316_set_ad_bound,
2042 ADT7516_AIN3_LOW);
2043static IIO_DEVICE_ATTR(ain4_high_value,
2044 S_IRUGO | S_IWUSR,
2045 adt7316_show_ad_bound, adt7316_set_ad_bound,
2046 ADT7516_AIN4_HIGH);
2047static IIO_DEVICE_ATTR(ain4_low_value,
2048 S_IRUGO | S_IWUSR,
2049 adt7316_show_ad_bound, adt7316_set_ad_bound,
2050 ADT7516_AIN4_LOW);
2051static IIO_DEVICE_ATTR(int_enabled,
2052 S_IRUGO | S_IWUSR,
2053 adt7316_show_int_enabled,
2054 adt7316_set_int_enabled, 0);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002055
2056static struct attribute *adt7316_event_attributes[] = {
Jonathan Cameron90f79e72011-05-18 14:41:05 +01002057 &iio_dev_attr_int_mask.dev_attr.attr,
2058 &iio_dev_attr_in_temp_high_value.dev_attr.attr,
2059 &iio_dev_attr_in_temp_low_value.dev_attr.attr,
2060 &iio_dev_attr_ex_temp_high_value.dev_attr.attr,
2061 &iio_dev_attr_ex_temp_low_value.dev_attr.attr,
2062 &iio_dev_attr_int_enabled.dev_attr.attr,
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002063 NULL,
2064};
2065
2066static struct attribute_group adt7316_event_attribute_group = {
2067 .attrs = adt7316_event_attributes,
Jonathan Cameron8e7d9672011-08-30 12:32:45 +01002068 .name = "events",
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002069};
2070
2071static struct attribute *adt7516_event_attributes[] = {
Jonathan Cameron90f79e72011-05-18 14:41:05 +01002072 &iio_dev_attr_int_mask.dev_attr.attr,
2073 &iio_dev_attr_in_temp_high_value.dev_attr.attr,
2074 &iio_dev_attr_in_temp_low_value.dev_attr.attr,
2075 &iio_dev_attr_ex_temp_ain1_high_value.dev_attr.attr,
2076 &iio_dev_attr_ex_temp_ain1_low_value.dev_attr.attr,
2077 &iio_dev_attr_ain2_high_value.dev_attr.attr,
2078 &iio_dev_attr_ain2_low_value.dev_attr.attr,
2079 &iio_dev_attr_ain3_high_value.dev_attr.attr,
2080 &iio_dev_attr_ain3_low_value.dev_attr.attr,
2081 &iio_dev_attr_ain4_high_value.dev_attr.attr,
2082 &iio_dev_attr_ain4_low_value.dev_attr.attr,
2083 &iio_dev_attr_int_enabled.dev_attr.attr,
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002084 NULL,
2085};
2086
2087static struct attribute_group adt7516_event_attribute_group = {
2088 .attrs = adt7516_event_attributes,
Jonathan Cameron8e7d9672011-08-30 12:32:45 +01002089 .name = "events",
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002090};
2091
2092#ifdef CONFIG_PM
2093int adt7316_disable(struct device *dev)
2094{
2095 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01002096 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002097
2098 return _adt7316_store_enabled(chip, 0);
2099}
2100EXPORT_SYMBOL(adt7316_disable);
2101
2102int adt7316_enable(struct device *dev)
2103{
2104 struct iio_dev *dev_info = dev_get_drvdata(dev);
Jonathan Cameron70be4292011-06-27 13:07:29 +01002105 struct adt7316_chip_info *chip = iio_priv(dev_info);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002106
2107 return _adt7316_store_enabled(chip, 1);
2108}
2109EXPORT_SYMBOL(adt7316_enable);
2110#endif
2111
Jonathan Cameron6fe81352011-05-18 14:42:37 +01002112static const struct iio_info adt7316_info = {
2113 .attrs = &adt7316_attribute_group,
Jonathan Cameron6fe81352011-05-18 14:42:37 +01002114 .event_attrs = &adt7316_event_attribute_group,
2115 .driver_module = THIS_MODULE,
2116};
2117
2118static const struct iio_info adt7516_info = {
2119 .attrs = &adt7516_attribute_group,
Jonathan Cameron6fe81352011-05-18 14:42:37 +01002120 .event_attrs = &adt7516_event_attribute_group,
2121 .driver_module = THIS_MODULE,
2122};
2123
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002124/*
2125 * device probe and remove
2126 */
2127int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus,
2128 const char *name)
2129{
2130 struct adt7316_chip_info *chip;
Jonathan Cameron70be4292011-06-27 13:07:29 +01002131 struct iio_dev *indio_dev;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002132 unsigned short *adt7316_platform_data = dev->platform_data;
2133 int ret = 0;
2134
Jonathan Cameron70be4292011-06-27 13:07:29 +01002135 indio_dev = iio_allocate_device(sizeof(*chip));
2136 if (indio_dev == NULL) {
2137 ret = -ENOMEM;
2138 goto error_ret;
2139 }
2140 chip = iio_priv(indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002141 /* this is only used for device removal purposes */
Jonathan Cameron70be4292011-06-27 13:07:29 +01002142 dev_set_drvdata(dev, indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002143
2144 chip->bus = *bus;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002145
2146 if (name[4] == '3')
2147 chip->id = ID_ADT7316 + (name[6] - '6');
2148 else if (name[4] == '5')
2149 chip->id = ID_ADT7516 + (name[6] - '6');
2150 else
2151 return -ENODEV;
2152
2153 chip->ldac_pin = adt7316_platform_data[1];
2154 if (chip->ldac_pin) {
2155 chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDCA;
2156 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
2157 chip->config1 |= ADT7516_SEL_AIN3;
2158 }
2159 chip->int_mask = ADT7316_TEMP_INT_MASK | ADT7316_VDD_INT_MASK;
2160 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
2161 chip->int_mask |= ADT7516_AIN_INT_MASK;
2162
Jonathan Cameron70be4292011-06-27 13:07:29 +01002163 indio_dev->dev.parent = dev;
Jonathan Cameron6fe81352011-05-18 14:42:37 +01002164 if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX)
Jonathan Cameron70be4292011-06-27 13:07:29 +01002165 indio_dev->info = &adt7516_info;
Jonathan Cameron6fe81352011-05-18 14:42:37 +01002166 else
Jonathan Cameron70be4292011-06-27 13:07:29 +01002167 indio_dev->info = &adt7316_info;
2168 indio_dev->name = name;
2169 indio_dev->modes = INDIO_DIRECT_MODE;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002170
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002171 if (chip->bus.irq > 0) {
2172 if (adt7316_platform_data[0])
2173 chip->bus.irq_flags = adt7316_platform_data[0];
2174
Jonathan Cameron90f79e72011-05-18 14:41:05 +01002175 ret = request_threaded_irq(chip->bus.irq,
2176 NULL,
2177 &adt7316_event_handler,
2178 chip->bus.irq_flags | IRQF_ONESHOT,
Jonathan Cameron70be4292011-06-27 13:07:29 +01002179 indio_dev->name,
2180 indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002181 if (ret)
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01002182 goto error_free_dev;
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002183
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002184 if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH)
2185 chip->config1 |= ADT7316_INT_POLARITY;
2186 }
2187
2188 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1);
2189 if (ret) {
2190 ret = -EIO;
2191 goto error_unreg_irq;
2192 }
2193
2194 ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, chip->config3);
2195 if (ret) {
2196 ret = -EIO;
2197 goto error_unreg_irq;
2198 }
2199
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01002200 ret = iio_device_register(indio_dev);
2201 if (ret)
2202 goto error_unreg_irq;
2203
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002204 dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n",
Jonathan Cameron70be4292011-06-27 13:07:29 +01002205 indio_dev->name);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002206
2207 return 0;
2208
2209error_unreg_irq:
Jonathan Cameron70be4292011-06-27 13:07:29 +01002210 free_irq(chip->bus.irq, indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002211error_free_dev:
Jonathan Cameron70be4292011-06-27 13:07:29 +01002212 iio_free_device(indio_dev);
2213error_ret:
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002214 return ret;
2215}
2216EXPORT_SYMBOL(adt7316_probe);
2217
2218int __devexit adt7316_remove(struct device *dev)
2219{
Jonathan Cameron70be4292011-06-27 13:07:29 +01002220 struct iio_dev *indio_dev = dev_get_drvdata(dev);
2221 struct adt7316_chip_info *chip = iio_priv(indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002222
Jonathan Camerond2fffd62011-10-14 14:46:58 +01002223 iio_device_unregister(indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002224 if (chip->bus.irq)
Jonathan Cameron70be4292011-06-27 13:07:29 +01002225 free_irq(chip->bus.irq, indio_dev);
Jonathan Camerond2fffd62011-10-14 14:46:58 +01002226 iio_free_device(indio_dev);
Sonic Zhang35f6b6b2010-10-27 21:43:52 -04002227
2228 return 0;
2229}
2230EXPORT_SYMBOL(adt7316_remove);
2231
2232MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
2233MODULE_DESCRIPTION("Analog Devices ADT7316/7/8 and ADT7516/7/9 digital"
2234 " temperature sensor, ADC and DAC driver");
2235MODULE_LICENSE("GPL v2");