Commit | Line | Data |
---|---|---|
ca5b4637 | 1 | // SPDX-License-Identifier: GPL-2.0 |
b9618c0c MH |
2 | /* |
3 | * AD7606 SPI ADC driver | |
4 | * | |
5 | * Copyright 2011 Analog Devices Inc. | |
b9618c0c MH |
6 | */ |
7 | ||
54160ae3 | 8 | #include <linux/delay.h> |
b9618c0c | 9 | #include <linux/device.h> |
b9618c0c | 10 | #include <linux/err.h> |
722407a4 | 11 | #include <linux/gpio/consumer.h> |
54160ae3 SP |
12 | #include <linux/interrupt.h> |
13 | #include <linux/kernel.h> | |
99c97852 | 14 | #include <linux/module.h> |
ae3babe1 | 15 | #include <linux/property.h> |
54160ae3 SP |
16 | #include <linux/regulator/consumer.h> |
17 | #include <linux/sched.h> | |
18 | #include <linux/slab.h> | |
19 | #include <linux/sysfs.h> | |
41f71e5e | 20 | #include <linux/util_macros.h> |
b9618c0c | 21 | |
06458e27 | 22 | #include <linux/iio/iio.h> |
06458e27 | 23 | #include <linux/iio/buffer.h> |
54160ae3 | 24 | #include <linux/iio/sysfs.h> |
cc49bd16 | 25 | #include <linux/iio/trigger.h> |
fa23105f | 26 | #include <linux/iio/triggered_buffer.h> |
54160ae3 | 27 | #include <linux/iio/trigger_consumer.h> |
b9618c0c MH |
28 | |
29 | #include "ad7606.h" | |
30 | ||
4ee03330 AA |
31 | /* |
32 | * Scales are computed as 5000/32768 and 10000/32768 respectively, | |
33 | * so that when applied to the raw values they provide mV values | |
34 | */ | |
6bf229ab | 35 | static const unsigned int ad7606_scale_avail[2] = { |
41f71e5e SP |
36 | 152588, 305176 |
37 | }; | |
38 | ||
f2a22e1e BB |
39 | |
40 | static const unsigned int ad7616_sw_scale_avail[3] = { | |
41 | 76293, 152588, 305176 | |
42 | }; | |
43 | ||
41f71e5e SP |
44 | static const unsigned int ad7606_oversampling_avail[7] = { |
45 | 1, 2, 4, 8, 16, 32, 64, | |
17be2a29 ERR |
46 | }; |
47 | ||
7989b4bb BB |
48 | static const unsigned int ad7616_oversampling_avail[8] = { |
49 | 1, 2, 4, 8, 16, 32, 64, 128, | |
50 | }; | |
51 | ||
fa23105f | 52 | static int ad7606_reset(struct ad7606_state *st) |
b9618c0c | 53 | { |
722407a4 LPC |
54 | if (st->gpio_reset) { |
55 | gpiod_set_value(st->gpio_reset, 1); | |
b9618c0c | 56 | ndelay(100); /* t_reset >= 100ns */ |
722407a4 | 57 | gpiod_set_value(st->gpio_reset, 0); |
b9618c0c MH |
58 | return 0; |
59 | } | |
60 | ||
61 | return -ENODEV; | |
62 | } | |
63 | ||
a444fa59 BB |
64 | static int ad7606_reg_access(struct iio_dev *indio_dev, |
65 | unsigned int reg, | |
66 | unsigned int writeval, | |
67 | unsigned int *readval) | |
68 | { | |
69 | struct ad7606_state *st = iio_priv(indio_dev); | |
70 | int ret; | |
71 | ||
72 | mutex_lock(&st->lock); | |
73 | if (readval) { | |
74 | ret = st->bops->reg_read(st, reg); | |
75 | if (ret < 0) | |
76 | goto err_unlock; | |
77 | *readval = ret; | |
78 | ret = 0; | |
79 | } else { | |
80 | ret = st->bops->reg_write(st, reg, writeval); | |
81 | } | |
82 | err_unlock: | |
83 | mutex_unlock(&st->lock); | |
84 | return ret; | |
85 | } | |
86 | ||
fa23105f | 87 | static int ad7606_read_samples(struct ad7606_state *st) |
91b7334b | 88 | { |
341826a0 | 89 | unsigned int num = st->chip_info->num_channels - 1; |
91b7334b LPC |
90 | u16 *data = st->data; |
91 | int ret; | |
92 | ||
93 | /* | |
94 | * The frstdata signal is set to high while and after reading the sample | |
95 | * of the first channel and low for all other channels. This can be used | |
96 | * to check that the incoming data is correctly aligned. During normal | |
97 | * operation the data should never become unaligned, but some glitch or | |
98 | * electrostatic discharge might cause an extra read or clock cycle. | |
99 | * Monitoring the frstdata signal allows to recover from such failure | |
100 | * situations. | |
101 | */ | |
102 | ||
722407a4 | 103 | if (st->gpio_frstdata) { |
91b7334b LPC |
104 | ret = st->bops->read_block(st->dev, 1, data); |
105 | if (ret) | |
106 | return ret; | |
107 | ||
722407a4 | 108 | if (!gpiod_get_value(st->gpio_frstdata)) { |
91b7334b LPC |
109 | ad7606_reset(st); |
110 | return -EIO; | |
111 | } | |
112 | ||
113 | data++; | |
114 | num--; | |
115 | } | |
116 | ||
117 | return st->bops->read_block(st->dev, num, data); | |
118 | } | |
119 | ||
fa23105f LPC |
120 | static irqreturn_t ad7606_trigger_handler(int irq, void *p) |
121 | { | |
122 | struct iio_poll_func *pf = p; | |
cc49bd16 SP |
123 | struct iio_dev *indio_dev = pf->indio_dev; |
124 | struct ad7606_state *st = iio_priv(indio_dev); | |
fa23105f LPC |
125 | int ret; |
126 | ||
cc49bd16 SP |
127 | mutex_lock(&st->lock); |
128 | ||
fa23105f LPC |
129 | ret = ad7606_read_samples(st); |
130 | if (ret == 0) | |
131 | iio_push_to_buffers_with_timestamp(indio_dev, st->data, | |
132 | iio_get_time_ns(indio_dev)); | |
133 | ||
fa23105f | 134 | iio_trigger_notify_done(indio_dev->trig); |
cc49bd16 SP |
135 | /* The rising edge of the CONVST signal starts a new conversion. */ |
136 | gpiod_set_value(st->gpio_convst, 1); | |
137 | ||
138 | mutex_unlock(&st->lock); | |
139 | ||
140 | return IRQ_HANDLED; | |
fa23105f LPC |
141 | } |
142 | ||
51fadb98 | 143 | static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) |
b9618c0c | 144 | { |
44039a67 | 145 | struct ad7606_state *st = iio_priv(indio_dev); |
b9618c0c MH |
146 | int ret; |
147 | ||
722407a4 | 148 | gpiod_set_value(st->gpio_convst, 1); |
557e585c SP |
149 | ret = wait_for_completion_timeout(&st->completion, |
150 | msecs_to_jiffies(1000)); | |
151 | if (!ret) { | |
152 | ret = -ETIMEDOUT; | |
b9618c0c | 153 | goto error_ret; |
557e585c | 154 | } |
b9618c0c | 155 | |
91b7334b LPC |
156 | ret = ad7606_read_samples(st); |
157 | if (ret == 0) | |
158 | ret = st->data[ch]; | |
b9618c0c MH |
159 | |
160 | error_ret: | |
722407a4 | 161 | gpiod_set_value(st->gpio_convst, 0); |
b9618c0c MH |
162 | |
163 | return ret; | |
164 | } | |
165 | ||
b9c44515 | 166 | static int ad7606_read_raw(struct iio_dev *indio_dev, |
1caf7cb4 MH |
167 | struct iio_chan_spec const *chan, |
168 | int *val, | |
169 | int *val2, | |
170 | long m) | |
b9618c0c | 171 | { |
3c23e9e8 | 172 | int ret, ch = 0; |
44039a67 | 173 | struct ad7606_state *st = iio_priv(indio_dev); |
1caf7cb4 MH |
174 | |
175 | switch (m) { | |
b11f98ff | 176 | case IIO_CHAN_INFO_RAW: |
ff5c37e3 AS |
177 | ret = iio_device_claim_direct_mode(indio_dev); |
178 | if (ret) | |
179 | return ret; | |
180 | ||
181 | ret = ad7606_scan_direct(indio_dev, chan->address); | |
182 | iio_device_release_direct_mode(indio_dev); | |
1caf7cb4 MH |
183 | |
184 | if (ret < 0) | |
185 | return ret; | |
c30685c6 | 186 | *val = (short)ret; |
1caf7cb4 | 187 | return IIO_VAL_INT; |
c8a9f805 | 188 | case IIO_CHAN_INFO_SCALE: |
3c23e9e8 BB |
189 | if (st->sw_mode_en) |
190 | ch = chan->address; | |
41f71e5e | 191 | *val = 0; |
3c23e9e8 | 192 | *val2 = st->scale_avail[st->range[ch]]; |
17be2a29 | 193 | return IIO_VAL_INT_PLUS_MICRO; |
4a5936da ERR |
194 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
195 | *val = st->oversampling; | |
196 | return IIO_VAL_INT; | |
1caf7cb4 MH |
197 | } |
198 | return -EINVAL; | |
b9618c0c MH |
199 | } |
200 | ||
6bf229ab SP |
201 | static ssize_t ad7606_show_avail(char *buf, const unsigned int *vals, |
202 | unsigned int n, bool micros) | |
b9618c0c | 203 | { |
6bf229ab SP |
204 | size_t len = 0; |
205 | int i; | |
aa960266 | 206 | |
6bf229ab SP |
207 | for (i = 0; i < n; i++) { |
208 | len += scnprintf(buf + len, PAGE_SIZE - len, | |
209 | micros ? "0.%06u " : "%u ", vals[i]); | |
210 | } | |
17be2a29 | 211 | buf[len - 1] = '\n'; |
b9618c0c | 212 | |
17be2a29 | 213 | return len; |
b9618c0c MH |
214 | } |
215 | ||
6bf229ab SP |
216 | static ssize_t in_voltage_scale_available_show(struct device *dev, |
217 | struct device_attribute *attr, | |
218 | char *buf) | |
219 | { | |
220 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
221 | struct ad7606_state *st = iio_priv(indio_dev); | |
222 | ||
223 | return ad7606_show_avail(buf, st->scale_avail, st->num_scales, true); | |
224 | } | |
225 | ||
17be2a29 | 226 | static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); |
b9618c0c | 227 | |
88dd0313 BB |
228 | static int ad7606_write_scale_hw(struct iio_dev *indio_dev, int ch, int val) |
229 | { | |
230 | struct ad7606_state *st = iio_priv(indio_dev); | |
231 | ||
232 | gpiod_set_value(st->gpio_range, val); | |
233 | ||
234 | return 0; | |
235 | } | |
236 | ||
237 | static int ad7606_write_os_hw(struct iio_dev *indio_dev, int val) | |
238 | { | |
239 | struct ad7606_state *st = iio_priv(indio_dev); | |
240 | DECLARE_BITMAP(values, 3); | |
241 | ||
242 | values[0] = val; | |
243 | ||
244 | gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, | |
245 | st->gpio_os->info, values); | |
246 | ||
247 | /* AD7616 requires a reset to update value */ | |
248 | if (st->chip_info->os_req_reset) | |
249 | ad7606_reset(st); | |
250 | ||
251 | return 0; | |
252 | } | |
253 | ||
4a5936da ERR |
254 | static int ad7606_write_raw(struct iio_dev *indio_dev, |
255 | struct iio_chan_spec const *chan, | |
256 | int val, | |
257 | int val2, | |
258 | long mask) | |
b9618c0c | 259 | { |
44039a67 | 260 | struct ad7606_state *st = iio_priv(indio_dev); |
88dd0313 | 261 | int i, ret, ch = 0; |
b9618c0c | 262 | |
4a5936da | 263 | switch (mask) { |
17be2a29 | 264 | case IIO_CHAN_INFO_SCALE: |
755d0da4 | 265 | mutex_lock(&st->lock); |
6bf229ab | 266 | i = find_closest(val2, st->scale_avail, st->num_scales); |
3c23e9e8 BB |
267 | if (st->sw_mode_en) |
268 | ch = chan->address; | |
269 | ret = st->write_scale(indio_dev, ch, i); | |
88dd0313 BB |
270 | if (ret < 0) { |
271 | mutex_unlock(&st->lock); | |
272 | return ret; | |
273 | } | |
274 | st->range[ch] = i; | |
755d0da4 | 275 | mutex_unlock(&st->lock); |
17be2a29 | 276 | |
41f71e5e | 277 | return 0; |
4a5936da ERR |
278 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
279 | if (val2) | |
280 | return -EINVAL; | |
6bf229ab SP |
281 | i = find_closest(val, st->oversampling_avail, |
282 | st->num_os_ratios); | |
755d0da4 | 283 | mutex_lock(&st->lock); |
88dd0313 BB |
284 | ret = st->write_os(indio_dev, i); |
285 | if (ret < 0) { | |
286 | mutex_unlock(&st->lock); | |
287 | return ret; | |
288 | } | |
6bf229ab | 289 | st->oversampling = st->oversampling_avail[i]; |
755d0da4 | 290 | mutex_unlock(&st->lock); |
722407a4 | 291 | |
4a5936da ERR |
292 | return 0; |
293 | default: | |
294 | return -EINVAL; | |
b9618c0c | 295 | } |
b9618c0c MH |
296 | } |
297 | ||
6bf229ab SP |
298 | static ssize_t ad7606_oversampling_ratio_avail(struct device *dev, |
299 | struct device_attribute *attr, | |
300 | char *buf) | |
301 | { | |
302 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
303 | struct ad7606_state *st = iio_priv(indio_dev); | |
304 | ||
305 | return ad7606_show_avail(buf, st->oversampling_avail, | |
306 | st->num_os_ratios, false); | |
307 | } | |
308 | ||
309 | static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444, | |
310 | ad7606_oversampling_ratio_avail, NULL, 0); | |
b9618c0c | 311 | |
9214cc6e | 312 | static struct attribute *ad7606_attributes_os_and_range[] = { |
17be2a29 | 313 | &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, |
6bf229ab | 314 | &iio_dev_attr_oversampling_ratio_available.dev_attr.attr, |
b9618c0c MH |
315 | NULL, |
316 | }; | |
317 | ||
9214cc6e JC |
318 | static const struct attribute_group ad7606_attribute_group_os_and_range = { |
319 | .attrs = ad7606_attributes_os_and_range, | |
320 | }; | |
b9618c0c | 321 | |
9214cc6e | 322 | static struct attribute *ad7606_attributes_os[] = { |
6bf229ab | 323 | &iio_dev_attr_oversampling_ratio_available.dev_attr.attr, |
9214cc6e JC |
324 | NULL, |
325 | }; | |
b9618c0c | 326 | |
9214cc6e JC |
327 | static const struct attribute_group ad7606_attribute_group_os = { |
328 | .attrs = ad7606_attributes_os, | |
329 | }; | |
330 | ||
331 | static struct attribute *ad7606_attributes_range[] = { | |
17be2a29 | 332 | &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, |
9214cc6e JC |
333 | NULL, |
334 | }; | |
335 | ||
336 | static const struct attribute_group ad7606_attribute_group_range = { | |
337 | .attrs = ad7606_attributes_range, | |
b9618c0c MH |
338 | }; |
339 | ||
bb9fc6ad AA |
340 | static const struct iio_chan_spec ad7605_channels[] = { |
341 | IIO_CHAN_SOFT_TIMESTAMP(4), | |
342 | AD7605_CHANNEL(0), | |
343 | AD7605_CHANNEL(1), | |
344 | AD7605_CHANNEL(2), | |
345 | AD7605_CHANNEL(3), | |
346 | }; | |
347 | ||
c89e2e2a LPC |
348 | static const struct iio_chan_spec ad7606_channels[] = { |
349 | IIO_CHAN_SOFT_TIMESTAMP(8), | |
50ac23be JC |
350 | AD7606_CHANNEL(0), |
351 | AD7606_CHANNEL(1), | |
352 | AD7606_CHANNEL(2), | |
353 | AD7606_CHANNEL(3), | |
354 | AD7606_CHANNEL(4), | |
355 | AD7606_CHANNEL(5), | |
356 | AD7606_CHANNEL(6), | |
357 | AD7606_CHANNEL(7), | |
1caf7cb4 MH |
358 | }; |
359 | ||
7989b4bb BB |
360 | /* |
361 | * The current assumption that this driver makes for AD7616, is that it's | |
362 | * working in Hardware Mode with Serial, Burst and Sequencer modes activated. | |
363 | * To activate them, following pins must be pulled high: | |
364 | * -SER/PAR | |
365 | * -SEQEN | |
366 | * And following pins must be pulled low: | |
367 | * -WR/BURST | |
368 | * -DB4/SER1W | |
369 | */ | |
370 | static const struct iio_chan_spec ad7616_channels[] = { | |
371 | IIO_CHAN_SOFT_TIMESTAMP(16), | |
372 | AD7606_CHANNEL(0), | |
373 | AD7606_CHANNEL(1), | |
374 | AD7606_CHANNEL(2), | |
375 | AD7606_CHANNEL(3), | |
376 | AD7606_CHANNEL(4), | |
377 | AD7606_CHANNEL(5), | |
378 | AD7606_CHANNEL(6), | |
379 | AD7606_CHANNEL(7), | |
380 | AD7606_CHANNEL(8), | |
381 | AD7606_CHANNEL(9), | |
382 | AD7606_CHANNEL(10), | |
383 | AD7606_CHANNEL(11), | |
384 | AD7606_CHANNEL(12), | |
385 | AD7606_CHANNEL(13), | |
386 | AD7606_CHANNEL(14), | |
387 | AD7606_CHANNEL(15), | |
388 | }; | |
389 | ||
b9618c0c | 390 | static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { |
54160ae3 | 391 | /* More devices added in future */ |
bb9fc6ad AA |
392 | [ID_AD7605_4] = { |
393 | .channels = ad7605_channels, | |
394 | .num_channels = 5, | |
395 | }, | |
b9618c0c | 396 | [ID_AD7606_8] = { |
c89e2e2a LPC |
397 | .channels = ad7606_channels, |
398 | .num_channels = 9, | |
6bf229ab SP |
399 | .oversampling_avail = ad7606_oversampling_avail, |
400 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | |
b9618c0c MH |
401 | }, |
402 | [ID_AD7606_6] = { | |
c89e2e2a LPC |
403 | .channels = ad7606_channels, |
404 | .num_channels = 7, | |
6bf229ab SP |
405 | .oversampling_avail = ad7606_oversampling_avail, |
406 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | |
b9618c0c MH |
407 | }, |
408 | [ID_AD7606_4] = { | |
c89e2e2a LPC |
409 | .channels = ad7606_channels, |
410 | .num_channels = 5, | |
6bf229ab SP |
411 | .oversampling_avail = ad7606_oversampling_avail, |
412 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | |
b9618c0c | 413 | }, |
d2a415c8 SP |
414 | [ID_AD7606B] = { |
415 | .channels = ad7606_channels, | |
416 | .num_channels = 9, | |
417 | .oversampling_avail = ad7606_oversampling_avail, | |
418 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | |
419 | }, | |
7989b4bb BB |
420 | [ID_AD7616] = { |
421 | .channels = ad7616_channels, | |
422 | .num_channels = 17, | |
423 | .oversampling_avail = ad7616_oversampling_avail, | |
424 | .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), | |
425 | .os_req_reset = true, | |
d2a415c8 | 426 | .init_delay_ms = 15, |
7989b4bb | 427 | }, |
b9618c0c MH |
428 | }; |
429 | ||
430 | static int ad7606_request_gpios(struct ad7606_state *st) | |
431 | { | |
722407a4 | 432 | struct device *dev = st->dev; |
b9618c0c | 433 | |
6620585a | 434 | st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start", |
722407a4 LPC |
435 | GPIOD_OUT_LOW); |
436 | if (IS_ERR(st->gpio_convst)) | |
437 | return PTR_ERR(st->gpio_convst); | |
b9618c0c | 438 | |
722407a4 LPC |
439 | st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); |
440 | if (IS_ERR(st->gpio_reset)) | |
441 | return PTR_ERR(st->gpio_reset); | |
b9618c0c | 442 | |
6620585a SP |
443 | st->gpio_range = devm_gpiod_get_optional(dev, "adi,range", |
444 | GPIOD_OUT_LOW); | |
722407a4 LPC |
445 | if (IS_ERR(st->gpio_range)) |
446 | return PTR_ERR(st->gpio_range); | |
b9618c0c | 447 | |
722407a4 LPC |
448 | st->gpio_standby = devm_gpiod_get_optional(dev, "standby", |
449 | GPIOD_OUT_HIGH); | |
450 | if (IS_ERR(st->gpio_standby)) | |
451 | return PTR_ERR(st->gpio_standby); | |
b9618c0c | 452 | |
6620585a | 453 | st->gpio_frstdata = devm_gpiod_get_optional(dev, "adi,first-data", |
722407a4 LPC |
454 | GPIOD_IN); |
455 | if (IS_ERR(st->gpio_frstdata)) | |
456 | return PTR_ERR(st->gpio_frstdata); | |
b9618c0c | 457 | |
6bf229ab | 458 | if (!st->chip_info->oversampling_num) |
bb9fc6ad AA |
459 | return 0; |
460 | ||
6620585a SP |
461 | st->gpio_os = devm_gpiod_get_array_optional(dev, |
462 | "adi,oversampling-ratio", | |
e480490c | 463 | GPIOD_OUT_LOW); |
dbdef9ba | 464 | return PTR_ERR_OR_ZERO(st->gpio_os); |
b9618c0c MH |
465 | } |
466 | ||
cc49bd16 SP |
467 | /* |
468 | * The BUSY signal indicates when conversions are in progress, so when a rising | |
469 | * edge of CONVST is applied, BUSY goes logic high and transitions low at the | |
470 | * end of the entire conversion process. The falling edge of the BUSY signal | |
471 | * triggers this interrupt. | |
b9618c0c MH |
472 | */ |
473 | static irqreturn_t ad7606_interrupt(int irq, void *dev_id) | |
474 | { | |
e61181d0 MH |
475 | struct iio_dev *indio_dev = dev_id; |
476 | struct ad7606_state *st = iio_priv(indio_dev); | |
b9618c0c | 477 | |
14555b14 | 478 | if (iio_buffer_enabled(indio_dev)) { |
cc49bd16 SP |
479 | gpiod_set_value(st->gpio_convst, 0); |
480 | iio_trigger_poll_chained(st->trig); | |
b9618c0c | 481 | } else { |
557e585c | 482 | complete(&st->completion); |
b9618c0c MH |
483 | } |
484 | ||
485 | return IRQ_HANDLED; | |
486 | }; | |
487 | ||
cc49bd16 SP |
488 | static int ad7606_validate_trigger(struct iio_dev *indio_dev, |
489 | struct iio_trigger *trig) | |
490 | { | |
491 | struct ad7606_state *st = iio_priv(indio_dev); | |
492 | ||
493 | if (st->trig != trig) | |
494 | return -EINVAL; | |
495 | ||
496 | return 0; | |
497 | } | |
498 | ||
499 | static int ad7606_buffer_postenable(struct iio_dev *indio_dev) | |
500 | { | |
501 | struct ad7606_state *st = iio_priv(indio_dev); | |
502 | ||
cc49bd16 SP |
503 | gpiod_set_value(st->gpio_convst, 1); |
504 | ||
505 | return 0; | |
506 | } | |
507 | ||
508 | static int ad7606_buffer_predisable(struct iio_dev *indio_dev) | |
509 | { | |
510 | struct ad7606_state *st = iio_priv(indio_dev); | |
511 | ||
512 | gpiod_set_value(st->gpio_convst, 0); | |
513 | ||
f11d59d8 | 514 | return 0; |
cc49bd16 SP |
515 | } |
516 | ||
517 | static const struct iio_buffer_setup_ops ad7606_buffer_ops = { | |
518 | .postenable = &ad7606_buffer_postenable, | |
519 | .predisable = &ad7606_buffer_predisable, | |
520 | }; | |
521 | ||
9214cc6e | 522 | static const struct iio_info ad7606_info_no_os_or_range = { |
6fe8135f | 523 | .read_raw = &ad7606_read_raw, |
cc49bd16 | 524 | .validate_trigger = &ad7606_validate_trigger, |
9214cc6e JC |
525 | }; |
526 | ||
527 | static const struct iio_info ad7606_info_os_and_range = { | |
9214cc6e | 528 | .read_raw = &ad7606_read_raw, |
4a5936da | 529 | .write_raw = &ad7606_write_raw, |
9214cc6e | 530 | .attrs = &ad7606_attribute_group_os_and_range, |
cc49bd16 | 531 | .validate_trigger = &ad7606_validate_trigger, |
9214cc6e JC |
532 | }; |
533 | ||
a444fa59 BB |
534 | static const struct iio_info ad7606_info_os_range_and_debug = { |
535 | .read_raw = &ad7606_read_raw, | |
536 | .write_raw = &ad7606_write_raw, | |
537 | .debugfs_reg_access = &ad7606_reg_access, | |
538 | .attrs = &ad7606_attribute_group_os_and_range, | |
539 | .validate_trigger = &ad7606_validate_trigger, | |
540 | }; | |
541 | ||
9214cc6e | 542 | static const struct iio_info ad7606_info_os = { |
9214cc6e | 543 | .read_raw = &ad7606_read_raw, |
4a5936da | 544 | .write_raw = &ad7606_write_raw, |
9214cc6e | 545 | .attrs = &ad7606_attribute_group_os, |
cc49bd16 | 546 | .validate_trigger = &ad7606_validate_trigger, |
9214cc6e JC |
547 | }; |
548 | ||
549 | static const struct iio_info ad7606_info_range = { | |
9214cc6e | 550 | .read_raw = &ad7606_read_raw, |
17be2a29 | 551 | .write_raw = &ad7606_write_raw, |
9214cc6e | 552 | .attrs = &ad7606_attribute_group_range, |
cc49bd16 SP |
553 | .validate_trigger = &ad7606_validate_trigger, |
554 | }; | |
555 | ||
556 | static const struct iio_trigger_ops ad7606_trigger_ops = { | |
557 | .validate_device = iio_trigger_validate_own_device, | |
6fe8135f JC |
558 | }; |
559 | ||
71faca73 LPC |
560 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, |
561 | const char *name, unsigned int id, | |
562 | const struct ad7606_bus_ops *bops) | |
b9618c0c | 563 | { |
b9618c0c | 564 | struct ad7606_state *st; |
26d25ae3 | 565 | int ret; |
3727245a | 566 | struct iio_dev *indio_dev; |
b9618c0c | 567 | |
3727245a SK |
568 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); |
569 | if (!indio_dev) | |
71faca73 | 570 | return -ENOMEM; |
b9618c0c | 571 | |
e61181d0 | 572 | st = iio_priv(indio_dev); |
c0683bfd | 573 | dev_set_drvdata(dev, indio_dev); |
e61181d0 | 574 | |
b9618c0c | 575 | st->dev = dev; |
755d0da4 | 576 | mutex_init(&st->lock); |
b9618c0c MH |
577 | st->bops = bops; |
578 | st->base_address = base_address; | |
17be2a29 | 579 | /* tied to logic low, analog input range is +/- 5V */ |
88dd0313 | 580 | st->range[0] = 0; |
e79e8027 | 581 | st->oversampling = 1; |
6bf229ab SP |
582 | st->scale_avail = ad7606_scale_avail; |
583 | st->num_scales = ARRAY_SIZE(ad7606_scale_avail); | |
b9618c0c | 584 | |
fd5b6c48 | 585 | ret = devm_regulator_get_enable(dev, "avcc"); |
c0683bfd | 586 | if (ret) |
fd5b6c48 MV |
587 | return dev_err_probe(dev, ret, |
588 | "Failed to enable specified AVcc supply\n"); | |
c0683bfd | 589 | |
bb9fc6ad AA |
590 | st->chip_info = &ad7606_chip_info_tbl[id]; |
591 | ||
6bf229ab SP |
592 | if (st->chip_info->oversampling_num) { |
593 | st->oversampling_avail = st->chip_info->oversampling_avail; | |
594 | st->num_os_ratios = st->chip_info->oversampling_num; | |
595 | } | |
596 | ||
722407a4 LPC |
597 | ret = ad7606_request_gpios(st); |
598 | if (ret) | |
c0683bfd | 599 | return ret; |
722407a4 | 600 | |
722407a4 LPC |
601 | if (st->gpio_os) { |
602 | if (st->gpio_range) | |
9214cc6e JC |
603 | indio_dev->info = &ad7606_info_os_and_range; |
604 | else | |
605 | indio_dev->info = &ad7606_info_os; | |
606 | } else { | |
722407a4 | 607 | if (st->gpio_range) |
9214cc6e JC |
608 | indio_dev->info = &ad7606_info_range; |
609 | else | |
610 | indio_dev->info = &ad7606_info_no_os_or_range; | |
611 | } | |
e61181d0 | 612 | indio_dev->modes = INDIO_DIRECT_MODE; |
063a51c5 | 613 | indio_dev->name = name; |
e61181d0 MH |
614 | indio_dev->channels = st->chip_info->channels; |
615 | indio_dev->num_channels = st->chip_info->num_channels; | |
b9618c0c | 616 | |
557e585c | 617 | init_completion(&st->completion); |
b9618c0c | 618 | |
b9618c0c MH |
619 | ret = ad7606_reset(st); |
620 | if (ret) | |
621 | dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); | |
622 | ||
c5d93137 | 623 | /* AD7616 requires al least 15ms to reconfigure after a reset */ |
d2a415c8 SP |
624 | if (st->chip_info->init_delay_ms) { |
625 | if (msleep_interruptible(st->chip_info->init_delay_ms)) | |
626 | return -ERESTARTSYS; | |
627 | } | |
c5d93137 | 628 | |
88dd0313 BB |
629 | st->write_scale = ad7606_write_scale_hw; |
630 | st->write_os = ad7606_write_os_hw; | |
631 | ||
a0c648c0 | 632 | if (st->bops->sw_mode_config) |
3c23e9e8 BB |
633 | st->sw_mode_en = device_property_present(st->dev, |
634 | "adi,sw-mode"); | |
635 | ||
636 | if (st->sw_mode_en) { | |
f2a22e1e BB |
637 | /* Scale of 0.076293 is only available in sw mode */ |
638 | st->scale_avail = ad7616_sw_scale_avail; | |
639 | st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); | |
640 | ||
3c23e9e8 BB |
641 | /* After reset, in software mode, ±10 V is set by default */ |
642 | memset32(st->range, 2, ARRAY_SIZE(st->range)); | |
a444fa59 | 643 | indio_dev->info = &ad7606_info_os_range_and_debug; |
3c23e9e8 | 644 | |
a0c648c0 | 645 | ret = st->bops->sw_mode_config(indio_dev); |
3c23e9e8 BB |
646 | if (ret < 0) |
647 | return ret; | |
648 | } | |
649 | ||
cc49bd16 | 650 | st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
15ea2878 JC |
651 | indio_dev->name, |
652 | iio_device_id(indio_dev)); | |
cc49bd16 SP |
653 | if (!st->trig) |
654 | return -ENOMEM; | |
655 | ||
656 | st->trig->ops = &ad7606_trigger_ops; | |
cc49bd16 SP |
657 | iio_trigger_set_drvdata(st->trig, indio_dev); |
658 | ret = devm_iio_trigger_register(dev, st->trig); | |
659 | if (ret) | |
660 | return ret; | |
661 | ||
662 | indio_dev->trig = iio_trigger_get(st->trig); | |
663 | ||
664 | ret = devm_request_threaded_irq(dev, irq, | |
665 | NULL, | |
666 | &ad7606_interrupt, | |
667 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | |
668 | name, indio_dev); | |
b9618c0c | 669 | if (ret) |
c0683bfd | 670 | return ret; |
b9618c0c | 671 | |
c0683bfd | 672 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, |
cc49bd16 | 673 | &iio_pollfunc_store_time, |
c0683bfd | 674 | &ad7606_trigger_handler, |
cc49bd16 | 675 | &ad7606_buffer_ops); |
26d25ae3 | 676 | if (ret) |
c0683bfd | 677 | return ret; |
b9618c0c | 678 | |
c0683bfd | 679 | return devm_iio_device_register(dev, indio_dev); |
b9618c0c | 680 | } |
59cea5bc | 681 | EXPORT_SYMBOL_NS_GPL(ad7606_probe, IIO_AD7606); |
b9618c0c | 682 | |
2c3a5236 LPC |
683 | #ifdef CONFIG_PM_SLEEP |
684 | ||
685 | static int ad7606_suspend(struct device *dev) | |
b9618c0c | 686 | { |
2c3a5236 | 687 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
e61181d0 MH |
688 | struct ad7606_state *st = iio_priv(indio_dev); |
689 | ||
722407a4 LPC |
690 | if (st->gpio_standby) { |
691 | gpiod_set_value(st->gpio_range, 1); | |
692 | gpiod_set_value(st->gpio_standby, 0); | |
b9618c0c | 693 | } |
2c3a5236 LPC |
694 | |
695 | return 0; | |
b9618c0c MH |
696 | } |
697 | ||
2c3a5236 | 698 | static int ad7606_resume(struct device *dev) |
b9618c0c | 699 | { |
2c3a5236 | 700 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
e61181d0 MH |
701 | struct ad7606_state *st = iio_priv(indio_dev); |
702 | ||
722407a4 | 703 | if (st->gpio_standby) { |
88dd0313 | 704 | gpiod_set_value(st->gpio_range, st->range[0]); |
722407a4 | 705 | gpiod_set_value(st->gpio_standby, 1); |
b9618c0c MH |
706 | ad7606_reset(st); |
707 | } | |
2c3a5236 LPC |
708 | |
709 | return 0; | |
b9618c0c | 710 | } |
2c3a5236 LPC |
711 | |
712 | SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume); | |
59cea5bc | 713 | EXPORT_SYMBOL_NS_GPL(ad7606_pm_ops, IIO_AD7606); |
2c3a5236 LPC |
714 | |
715 | #endif | |
b9618c0c | 716 | |
9920ed25 | 717 | MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); |
b9618c0c MH |
718 | MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); |
719 | MODULE_LICENSE("GPL v2"); |