Commit | Line | Data |
---|---|---|
349282d8 MH |
1 | /* |
2 | * AD7466/7/8 AD7476/5/7/8 (A) SPI ADC driver | |
3 | * | |
4 | * Copyright 2010 Analog Devices Inc. | |
5 | * | |
6 | * Licensed under the GPL-2 or later. | |
7 | */ | |
8 | ||
349282d8 MH |
9 | #include <linux/device.h> |
10 | #include <linux/kernel.h> | |
11 | #include <linux/slab.h> | |
12 | #include <linux/sysfs.h> | |
349282d8 MH |
13 | #include <linux/spi/spi.h> |
14 | #include <linux/regulator/consumer.h> | |
15 | #include <linux/err.h> | |
99c97852 | 16 | #include <linux/module.h> |
349282d8 | 17 | |
06458e27 JC |
18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> | |
20 | #include <linux/iio/buffer.h> | |
7a28fe3c LPC |
21 | #include <linux/iio/trigger_consumer.h> |
22 | #include <linux/iio/triggered_buffer.h> | |
349282d8 | 23 | |
7a28fe3c LPC |
24 | #define RES_MASK(bits) ((1 << (bits)) - 1) |
25 | ||
87c5b10f LPC |
26 | struct ad7476_state; |
27 | ||
7a28fe3c LPC |
28 | struct ad7476_chip_info { |
29 | unsigned int int_vref_uv; | |
30 | struct iio_chan_spec channel[2]; | |
87c5b10f | 31 | void (*reset)(struct ad7476_state *); |
7a28fe3c LPC |
32 | }; |
33 | ||
34 | struct ad7476_state { | |
35 | struct spi_device *spi; | |
36 | const struct ad7476_chip_info *chip_info; | |
37 | struct regulator *reg; | |
38 | struct spi_transfer xfer; | |
39 | struct spi_message msg; | |
40 | /* | |
41 | * DMA (thus cache coherency maintenance) requires the | |
42 | * transfer buffers to live in their own cache lines. | |
43 | * Make the buffer large enough for one 16 bit sample and one 64 bit | |
44 | * aligned 64 bit timestamp. | |
45 | */ | |
46 | unsigned char data[ALIGN(2, sizeof(s64)) + sizeof(s64)] | |
47 | ____cacheline_aligned; | |
48 | }; | |
49 | ||
50 | enum ad7476_supported_device_ids { | |
87c5b10f | 51 | ID_AD7091R, |
c26cc89e LPC |
52 | ID_AD7276, |
53 | ID_AD7277, | |
54 | ID_AD7278, | |
7a28fe3c LPC |
55 | ID_AD7466, |
56 | ID_AD7467, | |
57 | ID_AD7468, | |
4c337de8 LPC |
58 | ID_AD7495, |
59 | ID_AD7940, | |
7a28fe3c LPC |
60 | }; |
61 | ||
62 | static irqreturn_t ad7476_trigger_handler(int irq, void *p) | |
63 | { | |
64 | struct iio_poll_func *pf = p; | |
65 | struct iio_dev *indio_dev = pf->indio_dev; | |
66 | struct ad7476_state *st = iio_priv(indio_dev); | |
7a28fe3c LPC |
67 | int b_sent; |
68 | ||
69 | b_sent = spi_sync(st->spi, &st->msg); | |
70 | if (b_sent < 0) | |
71 | goto done; | |
72 | ||
b05583a7 LPC |
73 | iio_push_to_buffers_with_timestamp(indio_dev, st->data, |
74 | iio_get_time_ns()); | |
7a28fe3c LPC |
75 | done: |
76 | iio_trigger_notify_done(indio_dev->trig); | |
77 | ||
78 | return IRQ_HANDLED; | |
79 | } | |
349282d8 | 80 | |
87c5b10f LPC |
81 | static void ad7091_reset(struct ad7476_state *st) |
82 | { | |
83 | /* Any transfers with 8 scl cycles will reset the device */ | |
84 | spi_read(st->spi, st->data, 1); | |
85 | } | |
86 | ||
349282d8 MH |
87 | static int ad7476_scan_direct(struct ad7476_state *st) |
88 | { | |
349282d8 MH |
89 | int ret; |
90 | ||
668413e9 | 91 | ret = spi_sync(st->spi, &st->msg); |
349282d8 MH |
92 | if (ret) |
93 | return ret; | |
94 | ||
610a407c | 95 | return be16_to_cpup((__be16 *)st->data); |
349282d8 MH |
96 | } |
97 | ||
84f79ecb | 98 | static int ad7476_read_raw(struct iio_dev *indio_dev, |
c5e0819e JC |
99 | struct iio_chan_spec const *chan, |
100 | int *val, | |
101 | int *val2, | |
102 | long m) | |
349282d8 | 103 | { |
349282d8 | 104 | int ret; |
84f79ecb | 105 | struct ad7476_state *st = iio_priv(indio_dev); |
cb093e44 | 106 | int scale_uv; |
c5e0819e JC |
107 | |
108 | switch (m) { | |
b11f98ff | 109 | case IIO_CHAN_INFO_RAW: |
84f79ecb JC |
110 | mutex_lock(&indio_dev->mlock); |
111 | if (iio_buffer_enabled(indio_dev)) | |
78c32ed3 | 112 | ret = -EBUSY; |
c5e0819e JC |
113 | else |
114 | ret = ad7476_scan_direct(st); | |
84f79ecb | 115 | mutex_unlock(&indio_dev->mlock); |
c5e0819e JC |
116 | |
117 | if (ret < 0) | |
118 | return ret; | |
119 | *val = (ret >> st->chip_info->channel[0].scan_type.shift) & | |
120 | RES_MASK(st->chip_info->channel[0].scan_type.realbits); | |
121 | return IIO_VAL_INT; | |
c8a9f805 | 122 | case IIO_CHAN_INFO_SCALE: |
cb093e44 LPC |
123 | if (!st->chip_info->int_vref_uv) { |
124 | scale_uv = regulator_get_voltage(st->reg); | |
125 | if (scale_uv < 0) | |
126 | return scale_uv; | |
127 | } else { | |
128 | scale_uv = st->chip_info->int_vref_uv; | |
129 | } | |
d88c89db LPC |
130 | *val = scale_uv / 1000; |
131 | *val2 = chan->scan_type.realbits; | |
132 | return IIO_VAL_FRACTIONAL_LOG2; | |
c5e0819e JC |
133 | } |
134 | return -EINVAL; | |
349282d8 | 135 | } |
349282d8 | 136 | |
8c1033f7 | 137 | #define _AD7476_CHAN(bits, _shift, _info_mask_sep) \ |
85871cd8 JC |
138 | { \ |
139 | .type = IIO_VOLTAGE, \ | |
140 | .indexed = 1, \ | |
8c1033f7 JC |
141 | .info_mask_separate = _info_mask_sep, \ |
142 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
85871cd8 JC |
143 | .scan_type = { \ |
144 | .sign = 'u', \ | |
4c337de8 | 145 | .realbits = (bits), \ |
85871cd8 | 146 | .storagebits = 16, \ |
4c337de8 LPC |
147 | .shift = (_shift), \ |
148 | .endianness = IIO_BE, \ | |
85871cd8 JC |
149 | }, \ |
150 | } | |
151 | ||
87c5b10f | 152 | #define AD7476_CHAN(bits) _AD7476_CHAN((bits), 13 - (bits), \ |
8c1033f7 | 153 | BIT(IIO_CHAN_INFO_RAW)) |
87c5b10f | 154 | #define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \ |
8c1033f7 | 155 | BIT(IIO_CHAN_INFO_RAW)) |
87c5b10f | 156 | #define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0) |
4c337de8 | 157 | |
349282d8 | 158 | static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { |
87c5b10f LPC |
159 | [ID_AD7091R] = { |
160 | .channel[0] = AD7091R_CHAN(12), | |
161 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
162 | .reset = ad7091_reset, | |
163 | }, | |
c26cc89e LPC |
164 | [ID_AD7276] = { |
165 | .channel[0] = AD7940_CHAN(12), | |
166 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
167 | }, | |
168 | [ID_AD7277] = { | |
169 | .channel[0] = AD7940_CHAN(10), | |
170 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
171 | }, | |
172 | [ID_AD7278] = { | |
173 | .channel[0] = AD7940_CHAN(8), | |
174 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
175 | }, | |
349282d8 | 176 | [ID_AD7466] = { |
85871cd8 | 177 | .channel[0] = AD7476_CHAN(12), |
c5e0819e | 178 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
349282d8 MH |
179 | }, |
180 | [ID_AD7467] = { | |
85871cd8 | 181 | .channel[0] = AD7476_CHAN(10), |
c5e0819e | 182 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
349282d8 MH |
183 | }, |
184 | [ID_AD7468] = { | |
85871cd8 | 185 | .channel[0] = AD7476_CHAN(8), |
c5e0819e | 186 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
349282d8 | 187 | }, |
349282d8 | 188 | [ID_AD7495] = { |
85871cd8 | 189 | .channel[0] = AD7476_CHAN(12), |
c5e0819e | 190 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
cb093e44 | 191 | .int_vref_uv = 2500000, |
349282d8 | 192 | }, |
4c337de8 LPC |
193 | [ID_AD7940] = { |
194 | .channel[0] = AD7940_CHAN(14), | |
195 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
196 | }, | |
349282d8 MH |
197 | }; |
198 | ||
6fe8135f JC |
199 | static const struct iio_info ad7476_info = { |
200 | .driver_module = THIS_MODULE, | |
201 | .read_raw = &ad7476_read_raw, | |
202 | }; | |
203 | ||
fc52692c | 204 | static int ad7476_probe(struct spi_device *spi) |
349282d8 | 205 | { |
349282d8 | 206 | struct ad7476_state *st; |
67688105 | 207 | struct iio_dev *indio_dev; |
cb093e44 | 208 | int ret; |
349282d8 | 209 | |
4ea454d2 SK |
210 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
211 | if (!indio_dev) | |
212 | return -ENOMEM; | |
213 | ||
67688105 | 214 | st = iio_priv(indio_dev); |
349282d8 MH |
215 | st->chip_info = |
216 | &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | |
217 | ||
4ea454d2 SK |
218 | st->reg = devm_regulator_get(&spi->dev, "vcc"); |
219 | if (IS_ERR(st->reg)) | |
220 | return PTR_ERR(st->reg); | |
cb093e44 LPC |
221 | |
222 | ret = regulator_enable(st->reg); | |
223 | if (ret) | |
4ea454d2 | 224 | return ret; |
349282d8 | 225 | |
38f71aa9 | 226 | spi_set_drvdata(spi, indio_dev); |
349282d8 | 227 | |
349282d8 MH |
228 | st->spi = spi; |
229 | ||
ae639830 | 230 | /* Establish that the iio_dev is a child of the spi device */ |
67688105 JC |
231 | indio_dev->dev.parent = &spi->dev; |
232 | indio_dev->name = spi_get_device_id(spi)->name; | |
233 | indio_dev->modes = INDIO_DIRECT_MODE; | |
234 | indio_dev->channels = st->chip_info->channel; | |
235 | indio_dev->num_channels = 2; | |
236 | indio_dev->info = &ad7476_info; | |
349282d8 MH |
237 | /* Setup default message */ |
238 | ||
239 | st->xfer.rx_buf = &st->data; | |
c5e0819e | 240 | st->xfer.len = st->chip_info->channel[0].scan_type.storagebits / 8; |
349282d8 MH |
241 | |
242 | spi_message_init(&st->msg); | |
243 | spi_message_add_tail(&st->xfer, &st->msg); | |
244 | ||
7a28fe3c LPC |
245 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
246 | &ad7476_trigger_handler, NULL); | |
349282d8 | 247 | if (ret) |
67688105 | 248 | goto error_disable_reg; |
349282d8 | 249 | |
87c5b10f LPC |
250 | if (st->chip_info->reset) |
251 | st->chip_info->reset(st); | |
252 | ||
26d25ae3 JC |
253 | ret = iio_device_register(indio_dev); |
254 | if (ret) | |
255 | goto error_ring_unregister; | |
349282d8 MH |
256 | return 0; |
257 | ||
26d25ae3 | 258 | error_ring_unregister: |
7a28fe3c | 259 | iio_triggered_buffer_cleanup(indio_dev); |
349282d8 | 260 | error_disable_reg: |
cb093e44 | 261 | regulator_disable(st->reg); |
26d25ae3 | 262 | |
349282d8 MH |
263 | return ret; |
264 | } | |
265 | ||
fc52692c | 266 | static int ad7476_remove(struct spi_device *spi) |
349282d8 | 267 | { |
67688105 JC |
268 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
269 | struct ad7476_state *st = iio_priv(indio_dev); | |
67688105 | 270 | |
d2fffd6c | 271 | iio_device_unregister(indio_dev); |
7a28fe3c | 272 | iio_triggered_buffer_cleanup(indio_dev); |
cb093e44 | 273 | regulator_disable(st->reg); |
67688105 | 274 | |
349282d8 MH |
275 | return 0; |
276 | } | |
277 | ||
278 | static const struct spi_device_id ad7476_id[] = { | |
87c5b10f | 279 | {"ad7091r", ID_AD7091R}, |
c26cc89e LPC |
280 | {"ad7273", ID_AD7277}, |
281 | {"ad7274", ID_AD7276}, | |
282 | {"ad7276", ID_AD7276}, | |
283 | {"ad7277", ID_AD7277}, | |
284 | {"ad7278", ID_AD7278}, | |
349282d8 MH |
285 | {"ad7466", ID_AD7466}, |
286 | {"ad7467", ID_AD7467}, | |
287 | {"ad7468", ID_AD7468}, | |
fcc7800b LPC |
288 | {"ad7475", ID_AD7466}, |
289 | {"ad7476", ID_AD7466}, | |
290 | {"ad7476a", ID_AD7466}, | |
291 | {"ad7477", ID_AD7467}, | |
292 | {"ad7477a", ID_AD7467}, | |
293 | {"ad7478", ID_AD7468}, | |
294 | {"ad7478a", ID_AD7468}, | |
349282d8 | 295 | {"ad7495", ID_AD7495}, |
ac5332b1 LPC |
296 | {"ad7910", ID_AD7467}, |
297 | {"ad7920", ID_AD7466}, | |
4c337de8 | 298 | {"ad7940", ID_AD7940}, |
349282d8 MH |
299 | {} |
300 | }; | |
55e4390c | 301 | MODULE_DEVICE_TABLE(spi, ad7476_id); |
349282d8 MH |
302 | |
303 | static struct spi_driver ad7476_driver = { | |
304 | .driver = { | |
305 | .name = "ad7476", | |
349282d8 MH |
306 | .owner = THIS_MODULE, |
307 | }, | |
308 | .probe = ad7476_probe, | |
fc52692c | 309 | .remove = ad7476_remove, |
349282d8 MH |
310 | .id_table = ad7476_id, |
311 | }; | |
ae6ae6fe | 312 | module_spi_driver(ad7476_driver); |
349282d8 MH |
313 | |
314 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | |
ac5332b1 | 315 | MODULE_DESCRIPTION("Analog Devices AD7476 and similar 1-channel ADCs"); |
349282d8 | 316 | MODULE_LICENSE("GPL v2"); |