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