diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-09-04 11:26:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2012-09-08 05:20:09 -0400 |
commit | 7b123c85bbb3fadbd02b82d77d5aee0c399b0e06 (patch) | |
tree | 30d9f5e48ca28b1544ba239f107f4e8fea8e18af /drivers/iio | |
parent | bf83238019cf091a32d3a8aeddf22282af992843 (diff) |
staging:iio:adc: Add AD7791 driver
This patch adds support for the Analog Devices AD7787, AD7788, AD7789, AD7790
and AD7791 Sigma Delta Analog-to-Digital converters.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/adc/Kconfig | 12 | ||||
-rw-r--r-- | drivers/iio/adc/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/adc/ad7791.c | 460 |
3 files changed, 473 insertions, 0 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a2c50713b0b6..d0ae71ec2aa0 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig | |||
@@ -18,6 +18,18 @@ config AD7266 | |||
18 | Say yes here to build support for Analog Devices AD7265 and AD7266 | 18 | Say yes here to build support for Analog Devices AD7265 and AD7266 |
19 | ADCs. | 19 | ADCs. |
20 | 20 | ||
21 | config AD7791 | ||
22 | tristate "Analog Devices AD7791 ADC driver" | ||
23 | depends on SPI | ||
24 | select AD_SIGMA_DELTA | ||
25 | help | ||
26 | Say yes here to build support for Analog Devices AD7787, AD7788, AD7789, | ||
27 | AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say | ||
28 | N (but it is safe to say "Y"). | ||
29 | |||
30 | To compile this driver as a module, choose M here: the module will be | ||
31 | called ad7791. | ||
32 | |||
21 | config AT91_ADC | 33 | config AT91_ADC |
22 | tristate "Atmel AT91 ADC" | 34 | tristate "Atmel AT91 ADC" |
23 | depends on ARCH_AT91 | 35 | depends on ARCH_AT91 |
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 5989356c5735..f187ff6c2a16 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile | |||
@@ -4,4 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o | 5 | obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o |
6 | obj-$(CONFIG_AD7266) += ad7266.o | 6 | obj-$(CONFIG_AD7266) += ad7266.o |
7 | obj-$(CONFIG_AD7791) += ad7791.o | ||
7 | obj-$(CONFIG_AT91_ADC) += at91_adc.o | 8 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c new file mode 100644 index 000000000000..e93740843b2b --- /dev/null +++ b/drivers/iio/adc/ad7791.c | |||
@@ -0,0 +1,460 @@ | |||
1 | /* | ||
2 | * AD7787/AD7788/AD7789/AD7790/AD7791 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2012 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/sysfs.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/regulator/consumer.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | #include <linux/iio/iio.h> | ||
23 | #include <linux/iio/sysfs.h> | ||
24 | #include <linux/iio/buffer.h> | ||
25 | #include <linux/iio/trigger.h> | ||
26 | #include <linux/iio/trigger_consumer.h> | ||
27 | #include <linux/iio/triggered_buffer.h> | ||
28 | #include <linux/iio/adc/ad_sigma_delta.h> | ||
29 | |||
30 | #include <linux/platform_data/ad7791.h> | ||
31 | |||
32 | #define AD7791_REG_COMM 0x0 /* For writes */ | ||
33 | #define AD7791_REG_STATUS 0x0 /* For reads */ | ||
34 | #define AD7791_REG_MODE 0x1 | ||
35 | #define AD7791_REG_FILTER 0x2 | ||
36 | #define AD7791_REG_DATA 0x3 | ||
37 | |||
38 | #define AD7791_MODE_CONTINUOUS 0x00 | ||
39 | #define AD7791_MODE_SINGLE 0x02 | ||
40 | #define AD7791_MODE_POWERDOWN 0x03 | ||
41 | |||
42 | #define AD7791_CH_AIN1P_AIN1N 0x00 | ||
43 | #define AD7791_CH_AIN2 0x01 | ||
44 | #define AD7791_CH_AIN1N_AIN1N 0x02 | ||
45 | #define AD7791_CH_AVDD_MONITOR 0x03 | ||
46 | |||
47 | #define AD7791_FILTER_CLK_DIV_1 (0x0 << 4) | ||
48 | #define AD7791_FILTER_CLK_DIV_2 (0x1 << 4) | ||
49 | #define AD7791_FILTER_CLK_DIV_4 (0x2 << 4) | ||
50 | #define AD7791_FILTER_CLK_DIV_8 (0x3 << 4) | ||
51 | #define AD7791_FILTER_CLK_MASK (0x3 << 4) | ||
52 | #define AD7791_FILTER_RATE_120 0x0 | ||
53 | #define AD7791_FILTER_RATE_100 0x1 | ||
54 | #define AD7791_FILTER_RATE_33_3 0x2 | ||
55 | #define AD7791_FILTER_RATE_20 0x3 | ||
56 | #define AD7791_FILTER_RATE_16_6 0x4 | ||
57 | #define AD7791_FILTER_RATE_16_7 0x5 | ||
58 | #define AD7791_FILTER_RATE_13_3 0x6 | ||
59 | #define AD7791_FILTER_RATE_9_5 0x7 | ||
60 | #define AD7791_FILTER_RATE_MASK 0x7 | ||
61 | |||
62 | #define AD7791_MODE_BUFFER BIT(1) | ||
63 | #define AD7791_MODE_UNIPOLAR BIT(2) | ||
64 | #define AD7791_MODE_BURNOUT BIT(3) | ||
65 | #define AD7791_MODE_SEL_MASK (0x3 << 6) | ||
66 | #define AD7791_MODE_SEL(x) ((x) << 6) | ||
67 | |||
68 | #define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \ | ||
69 | const struct iio_chan_spec name[] = { \ | ||
70 | AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \ | ||
71 | (bits), (storagebits), 0), \ | ||
72 | AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \ | ||
73 | AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \ | ||
74 | (bits), (storagebits), 0), \ | ||
75 | AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \ | ||
76 | (bits), (storagebits), 0), \ | ||
77 | IIO_CHAN_SOFT_TIMESTAMP(4), \ | ||
78 | } | ||
79 | |||
80 | #define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \ | ||
81 | const struct iio_chan_spec name[] = { \ | ||
82 | AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \ | ||
83 | (bits), (storagebits), 0), \ | ||
84 | AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \ | ||
85 | (bits), (storagebits), 0), \ | ||
86 | AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \ | ||
87 | (bits), (storagebits), 0), \ | ||
88 | IIO_CHAN_SOFT_TIMESTAMP(3), \ | ||
89 | } | ||
90 | |||
91 | static DECLARE_AD7787_CHANNELS(ad7787_channels, 24, 32); | ||
92 | static DECLARE_AD7791_CHANNELS(ad7790_channels, 16, 16); | ||
93 | static DECLARE_AD7791_CHANNELS(ad7791_channels, 24, 32); | ||
94 | |||
95 | enum { | ||
96 | AD7787, | ||
97 | AD7788, | ||
98 | AD7789, | ||
99 | AD7790, | ||
100 | AD7791, | ||
101 | }; | ||
102 | |||
103 | enum ad7791_chip_info_flags { | ||
104 | AD7791_FLAG_HAS_FILTER = (1 << 0), | ||
105 | AD7791_FLAG_HAS_BUFFER = (1 << 1), | ||
106 | AD7791_FLAG_HAS_UNIPOLAR = (1 << 2), | ||
107 | AD7791_FLAG_HAS_BURNOUT = (1 << 3), | ||
108 | }; | ||
109 | |||
110 | struct ad7791_chip_info { | ||
111 | const struct iio_chan_spec *channels; | ||
112 | unsigned int num_channels; | ||
113 | enum ad7791_chip_info_flags flags; | ||
114 | }; | ||
115 | |||
116 | static const struct ad7791_chip_info ad7791_chip_infos[] = { | ||
117 | [AD7787] = { | ||
118 | .channels = ad7787_channels, | ||
119 | .num_channels = ARRAY_SIZE(ad7787_channels), | ||
120 | .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER | | ||
121 | AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT, | ||
122 | }, | ||
123 | [AD7788] = { | ||
124 | .channels = ad7790_channels, | ||
125 | .num_channels = ARRAY_SIZE(ad7790_channels), | ||
126 | .flags = AD7791_FLAG_HAS_UNIPOLAR, | ||
127 | }, | ||
128 | [AD7789] = { | ||
129 | .channels = ad7791_channels, | ||
130 | .num_channels = ARRAY_SIZE(ad7791_channels), | ||
131 | .flags = AD7791_FLAG_HAS_UNIPOLAR, | ||
132 | }, | ||
133 | [AD7790] = { | ||
134 | .channels = ad7790_channels, | ||
135 | .num_channels = ARRAY_SIZE(ad7790_channels), | ||
136 | .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER | | ||
137 | AD7791_FLAG_HAS_BURNOUT, | ||
138 | }, | ||
139 | [AD7791] = { | ||
140 | .channels = ad7791_channels, | ||
141 | .num_channels = ARRAY_SIZE(ad7791_channels), | ||
142 | .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER | | ||
143 | AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT, | ||
144 | }, | ||
145 | }; | ||
146 | |||
147 | struct ad7791_state { | ||
148 | struct ad_sigma_delta sd; | ||
149 | uint8_t mode; | ||
150 | uint8_t filter; | ||
151 | |||
152 | struct regulator *reg; | ||
153 | const struct ad7791_chip_info *info; | ||
154 | }; | ||
155 | |||
156 | static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd) | ||
157 | { | ||
158 | return container_of(sd, struct ad7791_state, sd); | ||
159 | } | ||
160 | |||
161 | static int ad7791_set_channel(struct ad_sigma_delta *sd, unsigned int channel) | ||
162 | { | ||
163 | ad_sd_set_comm(sd, channel); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int ad7791_set_mode(struct ad_sigma_delta *sd, | ||
169 | enum ad_sigma_delta_mode mode) | ||
170 | { | ||
171 | struct ad7791_state *st = ad_sigma_delta_to_ad7791(sd); | ||
172 | |||
173 | switch (mode) { | ||
174 | case AD_SD_MODE_CONTINUOUS: | ||
175 | mode = AD7791_MODE_CONTINUOUS; | ||
176 | break; | ||
177 | case AD_SD_MODE_SINGLE: | ||
178 | mode = AD7791_MODE_SINGLE; | ||
179 | break; | ||
180 | case AD_SD_MODE_IDLE: | ||
181 | case AD_SD_MODE_POWERDOWN: | ||
182 | mode = AD7791_MODE_POWERDOWN; | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | st->mode &= ~AD7791_MODE_SEL_MASK; | ||
187 | st->mode |= AD7791_MODE_SEL(mode); | ||
188 | |||
189 | return ad_sd_write_reg(sd, AD7791_REG_MODE, sizeof(st->mode), st->mode); | ||
190 | } | ||
191 | |||
192 | static const struct ad_sigma_delta_info ad7791_sigma_delta_info = { | ||
193 | .set_channel = ad7791_set_channel, | ||
194 | .set_mode = ad7791_set_mode, | ||
195 | .has_registers = true, | ||
196 | .addr_shift = 4, | ||
197 | .read_mask = BIT(3), | ||
198 | }; | ||
199 | |||
200 | static int ad7791_read_raw(struct iio_dev *indio_dev, | ||
201 | const struct iio_chan_spec *chan, int *val, int *val2, long info) | ||
202 | { | ||
203 | struct ad7791_state *st = iio_priv(indio_dev); | ||
204 | bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR); | ||
205 | unsigned long long scale_pv; | ||
206 | |||
207 | switch (info) { | ||
208 | case IIO_CHAN_INFO_RAW: | ||
209 | return ad_sigma_delta_single_conversion(indio_dev, chan, val); | ||
210 | case IIO_CHAN_INFO_OFFSET: | ||
211 | /** | ||
212 | * Unipolar: 0 to VREF | ||
213 | * Bipolar -VREF to VREF | ||
214 | **/ | ||
215 | if (unipolar) | ||
216 | *val = 0; | ||
217 | else | ||
218 | *val = -(1 << (chan->scan_type.realbits - 1)); | ||
219 | return IIO_VAL_INT; | ||
220 | case IIO_CHAN_INFO_SCALE: | ||
221 | /* The monitor channel uses an internal reference. */ | ||
222 | if (chan->address == AD7791_CH_AVDD_MONITOR) { | ||
223 | scale_pv = 5850000000000ULL; | ||
224 | } else { | ||
225 | int voltage_uv; | ||
226 | |||
227 | voltage_uv = regulator_get_voltage(st->reg); | ||
228 | if (voltage_uv < 0) | ||
229 | return voltage_uv; | ||
230 | scale_pv = (unsigned long long)voltage_uv * 1000000; | ||
231 | } | ||
232 | if (unipolar) | ||
233 | scale_pv >>= chan->scan_type.realbits; | ||
234 | else | ||
235 | scale_pv >>= chan->scan_type.realbits - 1; | ||
236 | *val2 = do_div(scale_pv, 1000000000); | ||
237 | *val = scale_pv; | ||
238 | |||
239 | return IIO_VAL_INT_PLUS_NANO; | ||
240 | } | ||
241 | |||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | static const char * const ad7791_sample_freq_avail[] = { | ||
246 | [AD7791_FILTER_RATE_120] = "120", | ||
247 | [AD7791_FILTER_RATE_100] = "100", | ||
248 | [AD7791_FILTER_RATE_33_3] = "33.3", | ||
249 | [AD7791_FILTER_RATE_20] = "20", | ||
250 | [AD7791_FILTER_RATE_16_6] = "16.6", | ||
251 | [AD7791_FILTER_RATE_16_7] = "16.7", | ||
252 | [AD7791_FILTER_RATE_13_3] = "13.3", | ||
253 | [AD7791_FILTER_RATE_9_5] = "9.5", | ||
254 | }; | ||
255 | |||
256 | static ssize_t ad7791_read_frequency(struct device *dev, | ||
257 | struct device_attribute *attr, char *buf) | ||
258 | { | ||
259 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
260 | struct ad7791_state *st = iio_priv(indio_dev); | ||
261 | unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK; | ||
262 | |||
263 | return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]); | ||
264 | } | ||
265 | |||
266 | static ssize_t ad7791_write_frequency(struct device *dev, | ||
267 | struct device_attribute *attr, const char *buf, size_t len) | ||
268 | { | ||
269 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
270 | struct ad7791_state *st = iio_priv(indio_dev); | ||
271 | int i, ret; | ||
272 | |||
273 | mutex_lock(&indio_dev->mlock); | ||
274 | if (iio_buffer_enabled(indio_dev)) { | ||
275 | mutex_unlock(&indio_dev->mlock); | ||
276 | return -EBUSY; | ||
277 | } | ||
278 | mutex_unlock(&indio_dev->mlock); | ||
279 | |||
280 | ret = -EINVAL; | ||
281 | |||
282 | for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) { | ||
283 | if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) { | ||
284 | |||
285 | mutex_lock(&indio_dev->mlock); | ||
286 | st->filter &= ~AD7791_FILTER_RATE_MASK; | ||
287 | st->filter |= i; | ||
288 | ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, | ||
289 | sizeof(st->filter), st->filter); | ||
290 | mutex_unlock(&indio_dev->mlock); | ||
291 | ret = 0; | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | return ret ? ret : len; | ||
297 | } | ||
298 | |||
299 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | ||
300 | ad7791_read_frequency, | ||
301 | ad7791_write_frequency); | ||
302 | |||
303 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5"); | ||
304 | |||
305 | static struct attribute *ad7791_attributes[] = { | ||
306 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | ||
307 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | ||
308 | NULL | ||
309 | }; | ||
310 | |||
311 | static const struct attribute_group ad7791_attribute_group = { | ||
312 | .attrs = ad7791_attributes, | ||
313 | }; | ||
314 | |||
315 | static const struct iio_info ad7791_info = { | ||
316 | .read_raw = &ad7791_read_raw, | ||
317 | .attrs = &ad7791_attribute_group, | ||
318 | .validate_trigger = ad_sd_validate_trigger, | ||
319 | .driver_module = THIS_MODULE, | ||
320 | }; | ||
321 | |||
322 | static const struct iio_info ad7791_no_filter_info = { | ||
323 | .read_raw = &ad7791_read_raw, | ||
324 | .validate_trigger = ad_sd_validate_trigger, | ||
325 | .driver_module = THIS_MODULE, | ||
326 | }; | ||
327 | |||
328 | static int __devinit ad7791_setup(struct ad7791_state *st, | ||
329 | struct ad7791_platform_data *pdata) | ||
330 | { | ||
331 | /* Set to poweron-reset default values */ | ||
332 | st->mode = AD7791_MODE_BUFFER; | ||
333 | st->filter = AD7791_FILTER_RATE_16_6; | ||
334 | |||
335 | if (!pdata) | ||
336 | return 0; | ||
337 | |||
338 | if ((st->info->flags & AD7791_FLAG_HAS_BUFFER) && !pdata->buffered) | ||
339 | st->mode &= ~AD7791_MODE_BUFFER; | ||
340 | |||
341 | if ((st->info->flags & AD7791_FLAG_HAS_BURNOUT) && | ||
342 | pdata->burnout_current) | ||
343 | st->mode |= AD7791_MODE_BURNOUT; | ||
344 | |||
345 | if ((st->info->flags & AD7791_FLAG_HAS_UNIPOLAR) && pdata->unipolar) | ||
346 | st->mode |= AD7791_MODE_UNIPOLAR; | ||
347 | |||
348 | return ad_sd_write_reg(&st->sd, AD7791_REG_MODE, sizeof(st->mode), | ||
349 | st->mode); | ||
350 | } | ||
351 | |||
352 | static int __devinit ad7791_probe(struct spi_device *spi) | ||
353 | { | ||
354 | struct ad7791_platform_data *pdata = spi->dev.platform_data; | ||
355 | struct iio_dev *indio_dev; | ||
356 | struct ad7791_state *st; | ||
357 | int ret; | ||
358 | |||
359 | if (!spi->irq) { | ||
360 | dev_err(&spi->dev, "Missing IRQ.\n"); | ||
361 | return -ENXIO; | ||
362 | } | ||
363 | |||
364 | indio_dev = iio_device_alloc(sizeof(*st)); | ||
365 | if (!indio_dev) | ||
366 | return -ENOMEM; | ||
367 | |||
368 | st = iio_priv(indio_dev); | ||
369 | |||
370 | st->reg = regulator_get(&spi->dev, "refin"); | ||
371 | if (IS_ERR(st->reg)) { | ||
372 | ret = PTR_ERR(st->reg); | ||
373 | goto err_iio_free; | ||
374 | } | ||
375 | |||
376 | ret = regulator_enable(st->reg); | ||
377 | if (ret) | ||
378 | goto error_put_reg; | ||
379 | |||
380 | st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data]; | ||
381 | ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info); | ||
382 | |||
383 | spi_set_drvdata(spi, indio_dev); | ||
384 | |||
385 | indio_dev->dev.parent = &spi->dev; | ||
386 | indio_dev->name = spi_get_device_id(spi)->name; | ||
387 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
388 | indio_dev->channels = st->info->channels; | ||
389 | indio_dev->num_channels = st->info->num_channels; | ||
390 | if (st->info->flags & AD7791_FLAG_HAS_FILTER) | ||
391 | indio_dev->info = &ad7791_info; | ||
392 | else | ||
393 | indio_dev->info = &ad7791_no_filter_info; | ||
394 | |||
395 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | ||
396 | if (ret) | ||
397 | goto error_disable_reg; | ||
398 | |||
399 | ret = ad7791_setup(st, pdata); | ||
400 | if (ret) | ||
401 | goto error_remove_trigger; | ||
402 | |||
403 | ret = iio_device_register(indio_dev); | ||
404 | if (ret) | ||
405 | goto error_remove_trigger; | ||
406 | |||
407 | return 0; | ||
408 | |||
409 | error_remove_trigger: | ||
410 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
411 | error_disable_reg: | ||
412 | regulator_disable(st->reg); | ||
413 | error_put_reg: | ||
414 | regulator_put(st->reg); | ||
415 | err_iio_free: | ||
416 | iio_device_free(indio_dev); | ||
417 | |||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | static int __devexit ad7791_remove(struct spi_device *spi) | ||
422 | { | ||
423 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
424 | struct ad7791_state *st = iio_priv(indio_dev); | ||
425 | |||
426 | iio_device_unregister(indio_dev); | ||
427 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
428 | |||
429 | regulator_disable(st->reg); | ||
430 | regulator_put(st->reg); | ||
431 | |||
432 | iio_device_free(indio_dev); | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static const struct spi_device_id ad7791_spi_ids[] = { | ||
438 | { "ad7787", AD7787 }, | ||
439 | { "ad7788", AD7788 }, | ||
440 | { "ad7789", AD7789 }, | ||
441 | { "ad7790", AD7790 }, | ||
442 | { "ad7791", AD7791 }, | ||
443 | {} | ||
444 | }; | ||
445 | MODULE_DEVICE_TABLE(spi, ad7791_spi_ids); | ||
446 | |||
447 | static struct spi_driver ad7791_driver = { | ||
448 | .driver = { | ||
449 | .name = "ad7791", | ||
450 | .owner = THIS_MODULE, | ||
451 | }, | ||
452 | .probe = ad7791_probe, | ||
453 | .remove = __devexit_p(ad7791_remove), | ||
454 | .id_table = ad7791_spi_ids, | ||
455 | }; | ||
456 | module_spi_driver(ad7791_driver); | ||
457 | |||
458 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
459 | MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver"); | ||
460 | MODULE_LICENSE("GPL v2"); | ||