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); | |
67 | s64 time_ns; | |
68 | int b_sent; | |
69 | ||
70 | b_sent = spi_sync(st->spi, &st->msg); | |
71 | if (b_sent < 0) | |
72 | goto done; | |
73 | ||
74 | time_ns = iio_get_time_ns(); | |
75 | ||
76 | if (indio_dev->scan_timestamp) | |
77 | ((s64 *)st->data)[1] = time_ns; | |
78 | ||
84b36ce5 | 79 | iio_push_to_buffers(indio_dev, st->data); |
7a28fe3c LPC |
80 | done: |
81 | iio_trigger_notify_done(indio_dev->trig); | |
82 | ||
83 | return IRQ_HANDLED; | |
84 | } | |
349282d8 | 85 | |
87c5b10f LPC |
86 | static void ad7091_reset(struct ad7476_state *st) |
87 | { | |
88 | /* Any transfers with 8 scl cycles will reset the device */ | |
89 | spi_read(st->spi, st->data, 1); | |
90 | } | |
91 | ||
349282d8 MH |
92 | static int ad7476_scan_direct(struct ad7476_state *st) |
93 | { | |
349282d8 MH |
94 | int ret; |
95 | ||
668413e9 | 96 | ret = spi_sync(st->spi, &st->msg); |
349282d8 MH |
97 | if (ret) |
98 | return ret; | |
99 | ||
610a407c | 100 | return be16_to_cpup((__be16 *)st->data); |
349282d8 MH |
101 | } |
102 | ||
84f79ecb | 103 | static int ad7476_read_raw(struct iio_dev *indio_dev, |
c5e0819e JC |
104 | struct iio_chan_spec const *chan, |
105 | int *val, | |
106 | int *val2, | |
107 | long m) | |
349282d8 | 108 | { |
349282d8 | 109 | int ret; |
84f79ecb | 110 | struct ad7476_state *st = iio_priv(indio_dev); |
cb093e44 | 111 | int scale_uv; |
c5e0819e JC |
112 | |
113 | switch (m) { | |
b11f98ff | 114 | case IIO_CHAN_INFO_RAW: |
84f79ecb JC |
115 | mutex_lock(&indio_dev->mlock); |
116 | if (iio_buffer_enabled(indio_dev)) | |
78c32ed3 | 117 | ret = -EBUSY; |
c5e0819e JC |
118 | else |
119 | ret = ad7476_scan_direct(st); | |
84f79ecb | 120 | mutex_unlock(&indio_dev->mlock); |
c5e0819e JC |
121 | |
122 | if (ret < 0) | |
123 | return ret; | |
124 | *val = (ret >> st->chip_info->channel[0].scan_type.shift) & | |
125 | RES_MASK(st->chip_info->channel[0].scan_type.realbits); | |
126 | return IIO_VAL_INT; | |
c8a9f805 | 127 | case IIO_CHAN_INFO_SCALE: |
cb093e44 LPC |
128 | if (!st->chip_info->int_vref_uv) { |
129 | scale_uv = regulator_get_voltage(st->reg); | |
130 | if (scale_uv < 0) | |
131 | return scale_uv; | |
132 | } else { | |
133 | scale_uv = st->chip_info->int_vref_uv; | |
134 | } | |
135 | scale_uv >>= chan->scan_type.realbits; | |
136 | *val = scale_uv / 1000; | |
137 | *val2 = (scale_uv % 1000) * 1000; | |
c5e0819e JC |
138 | return IIO_VAL_INT_PLUS_MICRO; |
139 | } | |
140 | return -EINVAL; | |
349282d8 | 141 | } |
349282d8 | 142 | |
8c1033f7 | 143 | #define _AD7476_CHAN(bits, _shift, _info_mask_sep) \ |
85871cd8 JC |
144 | { \ |
145 | .type = IIO_VOLTAGE, \ | |
146 | .indexed = 1, \ | |
8c1033f7 JC |
147 | .info_mask_separate = _info_mask_sep, \ |
148 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
85871cd8 JC |
149 | .scan_type = { \ |
150 | .sign = 'u', \ | |
4c337de8 | 151 | .realbits = (bits), \ |
85871cd8 | 152 | .storagebits = 16, \ |
4c337de8 LPC |
153 | .shift = (_shift), \ |
154 | .endianness = IIO_BE, \ | |
85871cd8 JC |
155 | }, \ |
156 | } | |
157 | ||
87c5b10f | 158 | #define AD7476_CHAN(bits) _AD7476_CHAN((bits), 13 - (bits), \ |
8c1033f7 | 159 | BIT(IIO_CHAN_INFO_RAW)) |
87c5b10f | 160 | #define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \ |
8c1033f7 | 161 | BIT(IIO_CHAN_INFO_RAW)) |
87c5b10f | 162 | #define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0) |
4c337de8 | 163 | |
349282d8 | 164 | static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { |
87c5b10f LPC |
165 | [ID_AD7091R] = { |
166 | .channel[0] = AD7091R_CHAN(12), | |
167 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
168 | .reset = ad7091_reset, | |
169 | }, | |
c26cc89e LPC |
170 | [ID_AD7276] = { |
171 | .channel[0] = AD7940_CHAN(12), | |
172 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
173 | }, | |
174 | [ID_AD7277] = { | |
175 | .channel[0] = AD7940_CHAN(10), | |
176 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
177 | }, | |
178 | [ID_AD7278] = { | |
179 | .channel[0] = AD7940_CHAN(8), | |
180 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
181 | }, | |
349282d8 | 182 | [ID_AD7466] = { |
85871cd8 | 183 | .channel[0] = AD7476_CHAN(12), |
c5e0819e | 184 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
349282d8 MH |
185 | }, |
186 | [ID_AD7467] = { | |
85871cd8 | 187 | .channel[0] = AD7476_CHAN(10), |
c5e0819e | 188 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
349282d8 MH |
189 | }, |
190 | [ID_AD7468] = { | |
85871cd8 | 191 | .channel[0] = AD7476_CHAN(8), |
c5e0819e | 192 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
349282d8 | 193 | }, |
349282d8 | 194 | [ID_AD7495] = { |
85871cd8 | 195 | .channel[0] = AD7476_CHAN(12), |
c5e0819e | 196 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
cb093e44 | 197 | .int_vref_uv = 2500000, |
349282d8 | 198 | }, |
4c337de8 LPC |
199 | [ID_AD7940] = { |
200 | .channel[0] = AD7940_CHAN(14), | |
201 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | |
202 | }, | |
349282d8 MH |
203 | }; |
204 | ||
6fe8135f JC |
205 | static const struct iio_info ad7476_info = { |
206 | .driver_module = THIS_MODULE, | |
207 | .read_raw = &ad7476_read_raw, | |
208 | }; | |
209 | ||
fc52692c | 210 | static int ad7476_probe(struct spi_device *spi) |
349282d8 | 211 | { |
349282d8 | 212 | struct ad7476_state *st; |
67688105 | 213 | struct iio_dev *indio_dev; |
cb093e44 | 214 | int ret; |
349282d8 | 215 | |
4ea454d2 SK |
216 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
217 | if (!indio_dev) | |
218 | return -ENOMEM; | |
219 | ||
67688105 | 220 | st = iio_priv(indio_dev); |
349282d8 MH |
221 | st->chip_info = |
222 | &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | |
223 | ||
4ea454d2 SK |
224 | st->reg = devm_regulator_get(&spi->dev, "vcc"); |
225 | if (IS_ERR(st->reg)) | |
226 | return PTR_ERR(st->reg); | |
cb093e44 LPC |
227 | |
228 | ret = regulator_enable(st->reg); | |
229 | if (ret) | |
4ea454d2 | 230 | return ret; |
349282d8 | 231 | |
38f71aa9 | 232 | spi_set_drvdata(spi, indio_dev); |
349282d8 | 233 | |
349282d8 MH |
234 | st->spi = spi; |
235 | ||
ae639830 | 236 | /* Establish that the iio_dev is a child of the spi device */ |
67688105 JC |
237 | indio_dev->dev.parent = &spi->dev; |
238 | indio_dev->name = spi_get_device_id(spi)->name; | |
239 | indio_dev->modes = INDIO_DIRECT_MODE; | |
240 | indio_dev->channels = st->chip_info->channel; | |
241 | indio_dev->num_channels = 2; | |
242 | indio_dev->info = &ad7476_info; | |
349282d8 MH |
243 | /* Setup default message */ |
244 | ||
245 | st->xfer.rx_buf = &st->data; | |
c5e0819e | 246 | st->xfer.len = st->chip_info->channel[0].scan_type.storagebits / 8; |
349282d8 MH |
247 | |
248 | spi_message_init(&st->msg); | |
249 | spi_message_add_tail(&st->xfer, &st->msg); | |
250 | ||
7a28fe3c LPC |
251 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
252 | &ad7476_trigger_handler, NULL); | |
349282d8 | 253 | if (ret) |
67688105 | 254 | goto error_disable_reg; |
349282d8 | 255 | |
87c5b10f LPC |
256 | if (st->chip_info->reset) |
257 | st->chip_info->reset(st); | |
258 | ||
26d25ae3 JC |
259 | ret = iio_device_register(indio_dev); |
260 | if (ret) | |
261 | goto error_ring_unregister; | |
349282d8 MH |
262 | return 0; |
263 | ||
26d25ae3 | 264 | error_ring_unregister: |
7a28fe3c | 265 | iio_triggered_buffer_cleanup(indio_dev); |
349282d8 | 266 | error_disable_reg: |
cb093e44 | 267 | regulator_disable(st->reg); |
26d25ae3 | 268 | |
349282d8 MH |
269 | return ret; |
270 | } | |
271 | ||
fc52692c | 272 | static int ad7476_remove(struct spi_device *spi) |
349282d8 | 273 | { |
67688105 JC |
274 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
275 | struct ad7476_state *st = iio_priv(indio_dev); | |
67688105 | 276 | |
d2fffd6c | 277 | iio_device_unregister(indio_dev); |
7a28fe3c | 278 | iio_triggered_buffer_cleanup(indio_dev); |
cb093e44 | 279 | regulator_disable(st->reg); |
67688105 | 280 | |
349282d8 MH |
281 | return 0; |
282 | } | |
283 | ||
284 | static const struct spi_device_id ad7476_id[] = { | |
87c5b10f | 285 | {"ad7091r", ID_AD7091R}, |
c26cc89e LPC |
286 | {"ad7273", ID_AD7277}, |
287 | {"ad7274", ID_AD7276}, | |
288 | {"ad7276", ID_AD7276}, | |
289 | {"ad7277", ID_AD7277}, | |
290 | {"ad7278", ID_AD7278}, | |
349282d8 MH |
291 | {"ad7466", ID_AD7466}, |
292 | {"ad7467", ID_AD7467}, | |
293 | {"ad7468", ID_AD7468}, | |
fcc7800b LPC |
294 | {"ad7475", ID_AD7466}, |
295 | {"ad7476", ID_AD7466}, | |
296 | {"ad7476a", ID_AD7466}, | |
297 | {"ad7477", ID_AD7467}, | |
298 | {"ad7477a", ID_AD7467}, | |
299 | {"ad7478", ID_AD7468}, | |
300 | {"ad7478a", ID_AD7468}, | |
349282d8 | 301 | {"ad7495", ID_AD7495}, |
ac5332b1 LPC |
302 | {"ad7910", ID_AD7467}, |
303 | {"ad7920", ID_AD7466}, | |
4c337de8 | 304 | {"ad7940", ID_AD7940}, |
349282d8 MH |
305 | {} |
306 | }; | |
55e4390c | 307 | MODULE_DEVICE_TABLE(spi, ad7476_id); |
349282d8 MH |
308 | |
309 | static struct spi_driver ad7476_driver = { | |
310 | .driver = { | |
311 | .name = "ad7476", | |
349282d8 MH |
312 | .owner = THIS_MODULE, |
313 | }, | |
314 | .probe = ad7476_probe, | |
fc52692c | 315 | .remove = ad7476_remove, |
349282d8 MH |
316 | .id_table = ad7476_id, |
317 | }; | |
ae6ae6fe | 318 | module_spi_driver(ad7476_driver); |
349282d8 MH |
319 | |
320 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | |
ac5332b1 | 321 | MODULE_DESCRIPTION("Analog Devices AD7476 and similar 1-channel ADCs"); |
349282d8 | 322 | MODULE_LICENSE("GPL v2"); |