2 * AD7887 SPI ADC driver
4 * Copyright 2010-2011 Analog Devices Inc.
6 * Licensed under the GPL-2.
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/sysfs.h>
13 #include <linux/spi/spi.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/err.h>
16 #include <linux/module.h>
20 #include "../buffer_generic.h"
25 static int ad7887_scan_direct(struct ad7887_state
*st
, unsigned ch
)
27 int ret
= spi_sync(st
->spi
, &st
->msg
[ch
]);
31 return (st
->data
[(ch
* 2)] << 8) | st
->data
[(ch
* 2) + 1];
34 static int ad7887_read_raw(struct iio_dev
*dev_info
,
35 struct iio_chan_spec
const *chan
,
41 struct ad7887_state
*st
= iio_priv(dev_info
);
42 unsigned int scale_uv
;
46 mutex_lock(&dev_info
->mlock
);
47 if (iio_buffer_enabled(dev_info
))
48 ret
= ad7887_scan_from_ring(st
, 1 << chan
->address
);
50 ret
= ad7887_scan_direct(st
, chan
->address
);
51 mutex_unlock(&dev_info
->mlock
);
55 *val
= (ret
>> st
->chip_info
->channel
[0].scan_type
.shift
) &
56 RES_MASK(st
->chip_info
->channel
[0].scan_type
.realbits
);
58 case (1 << IIO_CHAN_INFO_SCALE_SHARED
):
59 scale_uv
= (st
->int_vref_mv
* 1000)
60 >> st
->chip_info
->channel
[0].scan_type
.realbits
;
62 *val2
= (scale_uv
%1000)*1000;
63 return IIO_VAL_INT_PLUS_MICRO
;
69 static const struct ad7887_chip_info ad7887_chip_info_tbl
[] = {
71 * More devices added in future
74 .channel
[0] = IIO_CHAN(IIO_IN
, 0, 1, 0, NULL
, 1, 0,
75 (1 << IIO_CHAN_INFO_SCALE_SHARED
),
76 1, 1, IIO_ST('u', 12, 16, 0), 0),
78 .channel
[1] = IIO_CHAN(IIO_IN
, 0, 1, 0, NULL
, 0, 0,
79 (1 << IIO_CHAN_INFO_SCALE_SHARED
),
80 0, 0, IIO_ST('u', 12, 16, 0), 0),
82 .channel
[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
87 static const struct iio_info ad7887_info
= {
88 .read_raw
= &ad7887_read_raw
,
89 .driver_module
= THIS_MODULE
,
92 static int __devinit
ad7887_probe(struct spi_device
*spi
)
94 struct ad7887_platform_data
*pdata
= spi
->dev
.platform_data
;
95 struct ad7887_state
*st
;
96 int ret
, voltage_uv
= 0;
97 struct iio_dev
*indio_dev
= iio_allocate_device(sizeof(*st
));
99 if (indio_dev
== NULL
)
102 st
= iio_priv(indio_dev
);
104 st
->reg
= regulator_get(&spi
->dev
, "vcc");
105 if (!IS_ERR(st
->reg
)) {
106 ret
= regulator_enable(st
->reg
);
110 voltage_uv
= regulator_get_voltage(st
->reg
);
114 &ad7887_chip_info_tbl
[spi_get_device_id(spi
)->driver_data
];
116 spi_set_drvdata(spi
, indio_dev
);
119 /* Estabilish that the iio_dev is a child of the spi device */
120 indio_dev
->dev
.parent
= &spi
->dev
;
121 indio_dev
->name
= spi_get_device_id(spi
)->name
;
122 indio_dev
->info
= &ad7887_info
;
123 indio_dev
->modes
= INDIO_DIRECT_MODE
;
125 /* Setup default message */
127 st
->tx_cmd_buf
[0] = AD7887_CH_AIN0
| AD7887_PM_MODE4
|
128 ((pdata
&& pdata
->use_onchip_ref
) ?
131 st
->xfer
[0].rx_buf
= &st
->data
[0];
132 st
->xfer
[0].tx_buf
= &st
->tx_cmd_buf
[0];
135 spi_message_init(&st
->msg
[AD7887_CH0
]);
136 spi_message_add_tail(&st
->xfer
[0], &st
->msg
[AD7887_CH0
]);
138 if (pdata
&& pdata
->en_dual
) {
139 st
->tx_cmd_buf
[0] |= AD7887_DUAL
| AD7887_REF_DIS
;
141 st
->tx_cmd_buf
[2] = AD7887_CH_AIN1
| AD7887_DUAL
|
142 AD7887_REF_DIS
| AD7887_PM_MODE4
;
143 st
->tx_cmd_buf
[4] = AD7887_CH_AIN0
| AD7887_DUAL
|
144 AD7887_REF_DIS
| AD7887_PM_MODE4
;
145 st
->tx_cmd_buf
[6] = AD7887_CH_AIN1
| AD7887_DUAL
|
146 AD7887_REF_DIS
| AD7887_PM_MODE4
;
148 st
->xfer
[1].rx_buf
= &st
->data
[0];
149 st
->xfer
[1].tx_buf
= &st
->tx_cmd_buf
[2];
152 st
->xfer
[2].rx_buf
= &st
->data
[2];
153 st
->xfer
[2].tx_buf
= &st
->tx_cmd_buf
[4];
156 spi_message_init(&st
->msg
[AD7887_CH0_CH1
]);
157 spi_message_add_tail(&st
->xfer
[1], &st
->msg
[AD7887_CH0_CH1
]);
158 spi_message_add_tail(&st
->xfer
[2], &st
->msg
[AD7887_CH0_CH1
]);
160 st
->xfer
[3].rx_buf
= &st
->data
[0];
161 st
->xfer
[3].tx_buf
= &st
->tx_cmd_buf
[6];
164 spi_message_init(&st
->msg
[AD7887_CH1
]);
165 spi_message_add_tail(&st
->xfer
[3], &st
->msg
[AD7887_CH1
]);
167 if (pdata
&& pdata
->vref_mv
)
168 st
->int_vref_mv
= pdata
->vref_mv
;
170 st
->int_vref_mv
= voltage_uv
/ 1000;
172 dev_warn(&spi
->dev
, "reference voltage unspecified\n");
174 indio_dev
->channels
= st
->chip_info
->channel
;
175 indio_dev
->num_channels
= 3;
177 if (pdata
&& pdata
->vref_mv
)
178 st
->int_vref_mv
= pdata
->vref_mv
;
179 else if (pdata
&& pdata
->use_onchip_ref
)
180 st
->int_vref_mv
= st
->chip_info
->int_vref_mv
;
182 dev_warn(&spi
->dev
, "reference voltage unspecified\n");
184 indio_dev
->channels
= &st
->chip_info
->channel
[1];
185 indio_dev
->num_channels
= 2;
188 ret
= ad7887_register_ring_funcs_and_init(indio_dev
);
190 goto error_disable_reg
;
192 ret
= iio_buffer_register(indio_dev
,
194 indio_dev
->num_channels
);
196 goto error_cleanup_ring
;
198 ret
= iio_device_register(indio_dev
);
200 goto error_unregister_ring
;
203 error_unregister_ring
:
204 iio_buffer_unregister(indio_dev
);
206 ad7887_ring_cleanup(indio_dev
);
208 if (!IS_ERR(st
->reg
))
209 regulator_disable(st
->reg
);
211 if (!IS_ERR(st
->reg
))
212 regulator_put(st
->reg
);
213 iio_free_device(indio_dev
);
218 static int ad7887_remove(struct spi_device
*spi
)
220 struct iio_dev
*indio_dev
= spi_get_drvdata(spi
);
221 struct ad7887_state
*st
= iio_priv(indio_dev
);
223 iio_buffer_unregister(indio_dev
);
224 ad7887_ring_cleanup(indio_dev
);
225 if (!IS_ERR(st
->reg
)) {
226 regulator_disable(st
->reg
);
227 regulator_put(st
->reg
);
229 iio_device_unregister(indio_dev
);
234 static const struct spi_device_id ad7887_id
[] = {
235 {"ad7887", ID_AD7887
},
239 static struct spi_driver ad7887_driver
= {
242 .bus
= &spi_bus_type
,
243 .owner
= THIS_MODULE
,
245 .probe
= ad7887_probe
,
246 .remove
= __devexit_p(ad7887_remove
),
247 .id_table
= ad7887_id
,
250 static int __init
ad7887_init(void)
252 return spi_register_driver(&ad7887_driver
);
254 module_init(ad7887_init
);
256 static void __exit
ad7887_exit(void)
258 spi_unregister_driver(&ad7887_driver
);
260 module_exit(ad7887_exit
);
262 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
263 MODULE_DESCRIPTION("Analog Devices AD7887 ADC");
264 MODULE_LICENSE("GPL v2");
265 MODULE_ALIAS("spi:ad7887");