diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-06-04 05:36:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-05 01:02:25 -0400 |
commit | dbdc025bb239ce62c9b4d28c459a98f22ce9ec0a (patch) | |
tree | 2858c04b9d18852c1a4f4ca1c60c8e00b6180470 /drivers/iio/dac/ad5360.c | |
parent | 20374d1a36df3e20cd6742ba376684e5506254a8 (diff) |
staging:iio: Move DAC drivers out of staging
The IIO DAC drivers are in a reasonably good shape. They all make use of channel
spec and non of them provides non-documented sysfs attributes. Code style should
be OK as well, both checkpatch and coccicheck only report trivial issues.
So lets move the whole folder out of staging.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio/dac/ad5360.c')
-rw-r--r-- | drivers/iio/dac/ad5360.c | 570 |
1 files changed, 570 insertions, 0 deletions
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c new file mode 100644 index 000000000000..8fce84fe70b1 --- /dev/null +++ b/drivers/iio/dac/ad5360.c | |||
@@ -0,0 +1,570 @@ | |||
1 | /* | ||
2 | * Analog devices AD5360, AD5361, AD5362, AD5363, AD5370, AD5371, AD5373 | ||
3 | * multi-channel Digital to Analog Converters driver | ||
4 | * | ||
5 | * Copyright 2011 Analog Devices Inc. | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/device.h> | ||
11 | #include <linux/err.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | #include <linux/regulator/consumer.h> | ||
18 | |||
19 | #include <linux/iio/iio.h> | ||
20 | #include <linux/iio/sysfs.h> | ||
21 | |||
22 | #define AD5360_CMD(x) ((x) << 22) | ||
23 | #define AD5360_ADDR(x) ((x) << 16) | ||
24 | |||
25 | #define AD5360_READBACK_TYPE(x) ((x) << 13) | ||
26 | #define AD5360_READBACK_ADDR(x) ((x) << 7) | ||
27 | |||
28 | #define AD5360_CHAN_ADDR(chan) ((chan) + 0x8) | ||
29 | |||
30 | #define AD5360_CMD_WRITE_DATA 0x3 | ||
31 | #define AD5360_CMD_WRITE_OFFSET 0x2 | ||
32 | #define AD5360_CMD_WRITE_GAIN 0x1 | ||
33 | #define AD5360_CMD_SPECIAL_FUNCTION 0x0 | ||
34 | |||
35 | /* Special function register addresses */ | ||
36 | #define AD5360_REG_SF_NOP 0x0 | ||
37 | #define AD5360_REG_SF_CTRL 0x1 | ||
38 | #define AD5360_REG_SF_OFS(x) (0x2 + (x)) | ||
39 | #define AD5360_REG_SF_READBACK 0x5 | ||
40 | |||
41 | #define AD5360_SF_CTRL_PWR_DOWN BIT(0) | ||
42 | |||
43 | #define AD5360_READBACK_X1A 0x0 | ||
44 | #define AD5360_READBACK_X1B 0x1 | ||
45 | #define AD5360_READBACK_OFFSET 0x2 | ||
46 | #define AD5360_READBACK_GAIN 0x3 | ||
47 | #define AD5360_READBACK_SF 0x4 | ||
48 | |||
49 | |||
50 | /** | ||
51 | * struct ad5360_chip_info - chip specific information | ||
52 | * @channel_template: channel specification template | ||
53 | * @num_channels: number of channels | ||
54 | * @channels_per_group: number of channels per group | ||
55 | * @num_vrefs: number of vref supplies for the chip | ||
56 | */ | ||
57 | |||
58 | struct ad5360_chip_info { | ||
59 | struct iio_chan_spec channel_template; | ||
60 | unsigned int num_channels; | ||
61 | unsigned int channels_per_group; | ||
62 | unsigned int num_vrefs; | ||
63 | }; | ||
64 | |||
65 | /** | ||
66 | * struct ad5360_state - driver instance specific data | ||
67 | * @spi: spi_device | ||
68 | * @chip_info: chip model specific constants, available modes etc | ||
69 | * @vref_reg: vref supply regulators | ||
70 | * @ctrl: control register cache | ||
71 | * @data: spi transfer buffers | ||
72 | */ | ||
73 | |||
74 | struct ad5360_state { | ||
75 | struct spi_device *spi; | ||
76 | const struct ad5360_chip_info *chip_info; | ||
77 | struct regulator_bulk_data vref_reg[3]; | ||
78 | unsigned int ctrl; | ||
79 | |||
80 | /* | ||
81 | * DMA (thus cache coherency maintenance) requires the | ||
82 | * transfer buffers to live in their own cache lines. | ||
83 | */ | ||
84 | union { | ||
85 | __be32 d32; | ||
86 | u8 d8[4]; | ||
87 | } data[2] ____cacheline_aligned; | ||
88 | }; | ||
89 | |||
90 | enum ad5360_type { | ||
91 | ID_AD5360, | ||
92 | ID_AD5361, | ||
93 | ID_AD5362, | ||
94 | ID_AD5363, | ||
95 | ID_AD5370, | ||
96 | ID_AD5371, | ||
97 | ID_AD5372, | ||
98 | ID_AD5373, | ||
99 | }; | ||
100 | |||
101 | #define AD5360_CHANNEL(bits) { \ | ||
102 | .type = IIO_VOLTAGE, \ | ||
103 | .indexed = 1, \ | ||
104 | .output = 1, \ | ||
105 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | ||
106 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ | ||
107 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ | ||
108 | IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ | ||
109 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ | ||
110 | .scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \ | ||
111 | } | ||
112 | |||
113 | static const struct ad5360_chip_info ad5360_chip_info_tbl[] = { | ||
114 | [ID_AD5360] = { | ||
115 | .channel_template = AD5360_CHANNEL(16), | ||
116 | .num_channels = 16, | ||
117 | .channels_per_group = 8, | ||
118 | .num_vrefs = 2, | ||
119 | }, | ||
120 | [ID_AD5361] = { | ||
121 | .channel_template = AD5360_CHANNEL(14), | ||
122 | .num_channels = 16, | ||
123 | .channels_per_group = 8, | ||
124 | .num_vrefs = 2, | ||
125 | }, | ||
126 | [ID_AD5362] = { | ||
127 | .channel_template = AD5360_CHANNEL(16), | ||
128 | .num_channels = 8, | ||
129 | .channels_per_group = 4, | ||
130 | .num_vrefs = 2, | ||
131 | }, | ||
132 | [ID_AD5363] = { | ||
133 | .channel_template = AD5360_CHANNEL(14), | ||
134 | .num_channels = 8, | ||
135 | .channels_per_group = 4, | ||
136 | .num_vrefs = 2, | ||
137 | }, | ||
138 | [ID_AD5370] = { | ||
139 | .channel_template = AD5360_CHANNEL(16), | ||
140 | .num_channels = 40, | ||
141 | .channels_per_group = 8, | ||
142 | .num_vrefs = 2, | ||
143 | }, | ||
144 | [ID_AD5371] = { | ||
145 | .channel_template = AD5360_CHANNEL(14), | ||
146 | .num_channels = 40, | ||
147 | .channels_per_group = 8, | ||
148 | .num_vrefs = 3, | ||
149 | }, | ||
150 | [ID_AD5372] = { | ||
151 | .channel_template = AD5360_CHANNEL(16), | ||
152 | .num_channels = 32, | ||
153 | .channels_per_group = 8, | ||
154 | .num_vrefs = 2, | ||
155 | }, | ||
156 | [ID_AD5373] = { | ||
157 | .channel_template = AD5360_CHANNEL(14), | ||
158 | .num_channels = 32, | ||
159 | .channels_per_group = 8, | ||
160 | .num_vrefs = 2, | ||
161 | }, | ||
162 | }; | ||
163 | |||
164 | static unsigned int ad5360_get_channel_vref_index(struct ad5360_state *st, | ||
165 | unsigned int channel) | ||
166 | { | ||
167 | unsigned int i; | ||
168 | |||
169 | /* The first groups have their own vref, while the remaining groups | ||
170 | * share the last vref */ | ||
171 | i = channel / st->chip_info->channels_per_group; | ||
172 | if (i >= st->chip_info->num_vrefs) | ||
173 | i = st->chip_info->num_vrefs - 1; | ||
174 | |||
175 | return i; | ||
176 | } | ||
177 | |||
178 | static int ad5360_get_channel_vref(struct ad5360_state *st, | ||
179 | unsigned int channel) | ||
180 | { | ||
181 | unsigned int i = ad5360_get_channel_vref_index(st, channel); | ||
182 | |||
183 | return regulator_get_voltage(st->vref_reg[i].consumer); | ||
184 | } | ||
185 | |||
186 | |||
187 | static int ad5360_write_unlocked(struct iio_dev *indio_dev, | ||
188 | unsigned int cmd, unsigned int addr, unsigned int val, | ||
189 | unsigned int shift) | ||
190 | { | ||
191 | struct ad5360_state *st = iio_priv(indio_dev); | ||
192 | |||
193 | val <<= shift; | ||
194 | val |= AD5360_CMD(cmd) | AD5360_ADDR(addr); | ||
195 | st->data[0].d32 = cpu_to_be32(val); | ||
196 | |||
197 | return spi_write(st->spi, &st->data[0].d8[1], 3); | ||
198 | } | ||
199 | |||
200 | static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd, | ||
201 | unsigned int addr, unsigned int val, unsigned int shift) | ||
202 | { | ||
203 | int ret; | ||
204 | |||
205 | mutex_lock(&indio_dev->mlock); | ||
206 | ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift); | ||
207 | mutex_unlock(&indio_dev->mlock); | ||
208 | |||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, | ||
213 | unsigned int addr) | ||
214 | { | ||
215 | struct ad5360_state *st = iio_priv(indio_dev); | ||
216 | struct spi_message m; | ||
217 | int ret; | ||
218 | struct spi_transfer t[] = { | ||
219 | { | ||
220 | .tx_buf = &st->data[0].d8[1], | ||
221 | .len = 3, | ||
222 | .cs_change = 1, | ||
223 | }, { | ||
224 | .rx_buf = &st->data[1].d8[1], | ||
225 | .len = 3, | ||
226 | }, | ||
227 | }; | ||
228 | |||
229 | spi_message_init(&m); | ||
230 | spi_message_add_tail(&t[0], &m); | ||
231 | spi_message_add_tail(&t[1], &m); | ||
232 | |||
233 | mutex_lock(&indio_dev->mlock); | ||
234 | |||
235 | st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) | | ||
236 | AD5360_ADDR(AD5360_REG_SF_READBACK) | | ||
237 | AD5360_READBACK_TYPE(type) | | ||
238 | AD5360_READBACK_ADDR(addr)); | ||
239 | |||
240 | ret = spi_sync(st->spi, &m); | ||
241 | if (ret >= 0) | ||
242 | ret = be32_to_cpu(st->data[1].d32) & 0xffff; | ||
243 | |||
244 | mutex_unlock(&indio_dev->mlock); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static ssize_t ad5360_read_dac_powerdown(struct device *dev, | ||
250 | struct device_attribute *attr, | ||
251 | char *buf) | ||
252 | { | ||
253 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
254 | struct ad5360_state *st = iio_priv(indio_dev); | ||
255 | |||
256 | return sprintf(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN)); | ||
257 | } | ||
258 | |||
259 | static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set, | ||
260 | unsigned int clr) | ||
261 | { | ||
262 | struct ad5360_state *st = iio_priv(indio_dev); | ||
263 | unsigned int ret; | ||
264 | |||
265 | mutex_lock(&indio_dev->mlock); | ||
266 | |||
267 | st->ctrl |= set; | ||
268 | st->ctrl &= ~clr; | ||
269 | |||
270 | ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, | ||
271 | AD5360_REG_SF_CTRL, st->ctrl, 0); | ||
272 | |||
273 | mutex_unlock(&indio_dev->mlock); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static ssize_t ad5360_write_dac_powerdown(struct device *dev, | ||
279 | struct device_attribute *attr, const char *buf, size_t len) | ||
280 | { | ||
281 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
282 | bool pwr_down; | ||
283 | int ret; | ||
284 | |||
285 | ret = strtobool(buf, &pwr_down); | ||
286 | if (ret) | ||
287 | return ret; | ||
288 | |||
289 | if (pwr_down) | ||
290 | ret = ad5360_update_ctrl(indio_dev, AD5360_SF_CTRL_PWR_DOWN, 0); | ||
291 | else | ||
292 | ret = ad5360_update_ctrl(indio_dev, 0, AD5360_SF_CTRL_PWR_DOWN); | ||
293 | |||
294 | return ret ? ret : len; | ||
295 | } | ||
296 | |||
297 | static IIO_DEVICE_ATTR(out_voltage_powerdown, | ||
298 | S_IRUGO | S_IWUSR, | ||
299 | ad5360_read_dac_powerdown, | ||
300 | ad5360_write_dac_powerdown, 0); | ||
301 | |||
302 | static struct attribute *ad5360_attributes[] = { | ||
303 | &iio_dev_attr_out_voltage_powerdown.dev_attr.attr, | ||
304 | NULL, | ||
305 | }; | ||
306 | |||
307 | static const struct attribute_group ad5360_attribute_group = { | ||
308 | .attrs = ad5360_attributes, | ||
309 | }; | ||
310 | |||
311 | static int ad5360_write_raw(struct iio_dev *indio_dev, | ||
312 | struct iio_chan_spec const *chan, | ||
313 | int val, | ||
314 | int val2, | ||
315 | long mask) | ||
316 | { | ||
317 | struct ad5360_state *st = iio_priv(indio_dev); | ||
318 | int max_val = (1 << chan->scan_type.realbits); | ||
319 | unsigned int ofs_index; | ||
320 | |||
321 | switch (mask) { | ||
322 | case IIO_CHAN_INFO_RAW: | ||
323 | if (val >= max_val || val < 0) | ||
324 | return -EINVAL; | ||
325 | |||
326 | return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, | ||
327 | chan->address, val, chan->scan_type.shift); | ||
328 | |||
329 | case IIO_CHAN_INFO_CALIBBIAS: | ||
330 | if (val >= max_val || val < 0) | ||
331 | return -EINVAL; | ||
332 | |||
333 | return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET, | ||
334 | chan->address, val, chan->scan_type.shift); | ||
335 | |||
336 | case IIO_CHAN_INFO_CALIBSCALE: | ||
337 | if (val >= max_val || val < 0) | ||
338 | return -EINVAL; | ||
339 | |||
340 | return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN, | ||
341 | chan->address, val, chan->scan_type.shift); | ||
342 | |||
343 | case IIO_CHAN_INFO_OFFSET: | ||
344 | if (val <= -max_val || val > 0) | ||
345 | return -EINVAL; | ||
346 | |||
347 | val = -val; | ||
348 | |||
349 | /* offset is supposed to have the same scale as raw, but it | ||
350 | * is always 14bits wide, so on a chip where the raw value has | ||
351 | * more bits, we need to shift offset. */ | ||
352 | val >>= (chan->scan_type.realbits - 14); | ||
353 | |||
354 | /* There is one DAC offset register per vref. Changing one | ||
355 | * channels offset will also change the offset for all other | ||
356 | * channels which share the same vref supply. */ | ||
357 | ofs_index = ad5360_get_channel_vref_index(st, chan->channel); | ||
358 | return ad5360_write(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, | ||
359 | AD5360_REG_SF_OFS(ofs_index), val, 0); | ||
360 | default: | ||
361 | break; | ||
362 | } | ||
363 | |||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | static int ad5360_read_raw(struct iio_dev *indio_dev, | ||
368 | struct iio_chan_spec const *chan, | ||
369 | int *val, | ||
370 | int *val2, | ||
371 | long m) | ||
372 | { | ||
373 | struct ad5360_state *st = iio_priv(indio_dev); | ||
374 | unsigned int ofs_index; | ||
375 | int scale_uv; | ||
376 | int ret; | ||
377 | |||
378 | switch (m) { | ||
379 | case IIO_CHAN_INFO_RAW: | ||
380 | ret = ad5360_read(indio_dev, AD5360_READBACK_X1A, | ||
381 | chan->address); | ||
382 | if (ret < 0) | ||
383 | return ret; | ||
384 | *val = ret >> chan->scan_type.shift; | ||
385 | return IIO_VAL_INT; | ||
386 | case IIO_CHAN_INFO_SCALE: | ||
387 | /* vout = 4 * vref * dac_code */ | ||
388 | scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; | ||
389 | if (scale_uv < 0) | ||
390 | return scale_uv; | ||
391 | |||
392 | scale_uv >>= (chan->scan_type.realbits); | ||
393 | *val = scale_uv / 100000; | ||
394 | *val2 = (scale_uv % 100000) * 10; | ||
395 | return IIO_VAL_INT_PLUS_MICRO; | ||
396 | case IIO_CHAN_INFO_CALIBBIAS: | ||
397 | ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, | ||
398 | chan->address); | ||
399 | if (ret < 0) | ||
400 | return ret; | ||
401 | *val = ret; | ||
402 | return IIO_VAL_INT; | ||
403 | case IIO_CHAN_INFO_CALIBSCALE: | ||
404 | ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, | ||
405 | chan->address); | ||
406 | if (ret < 0) | ||
407 | return ret; | ||
408 | *val = ret; | ||
409 | return IIO_VAL_INT; | ||
410 | case IIO_CHAN_INFO_OFFSET: | ||
411 | ofs_index = ad5360_get_channel_vref_index(st, chan->channel); | ||
412 | ret = ad5360_read(indio_dev, AD5360_READBACK_SF, | ||
413 | AD5360_REG_SF_OFS(ofs_index)); | ||
414 | if (ret < 0) | ||
415 | return ret; | ||
416 | |||
417 | ret <<= (chan->scan_type.realbits - 14); | ||
418 | *val = -ret; | ||
419 | return IIO_VAL_INT; | ||
420 | } | ||
421 | |||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | static const struct iio_info ad5360_info = { | ||
426 | .read_raw = ad5360_read_raw, | ||
427 | .write_raw = ad5360_write_raw, | ||
428 | .attrs = &ad5360_attribute_group, | ||
429 | .driver_module = THIS_MODULE, | ||
430 | }; | ||
431 | |||
432 | static const char * const ad5360_vref_name[] = { | ||
433 | "vref0", "vref1", "vref2" | ||
434 | }; | ||
435 | |||
436 | static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) | ||
437 | { | ||
438 | struct ad5360_state *st = iio_priv(indio_dev); | ||
439 | struct iio_chan_spec *channels; | ||
440 | unsigned int i; | ||
441 | |||
442 | channels = kcalloc(st->chip_info->num_channels, | ||
443 | sizeof(struct iio_chan_spec), GFP_KERNEL); | ||
444 | |||
445 | if (!channels) | ||
446 | return -ENOMEM; | ||
447 | |||
448 | for (i = 0; i < st->chip_info->num_channels; ++i) { | ||
449 | channels[i] = st->chip_info->channel_template; | ||
450 | channels[i].channel = i; | ||
451 | channels[i].address = AD5360_CHAN_ADDR(i); | ||
452 | } | ||
453 | |||
454 | indio_dev->channels = channels; | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static int __devinit ad5360_probe(struct spi_device *spi) | ||
460 | { | ||
461 | enum ad5360_type type = spi_get_device_id(spi)->driver_data; | ||
462 | struct iio_dev *indio_dev; | ||
463 | struct ad5360_state *st; | ||
464 | unsigned int i; | ||
465 | int ret; | ||
466 | |||
467 | indio_dev = iio_device_alloc(sizeof(*st)); | ||
468 | if (indio_dev == NULL) { | ||
469 | dev_err(&spi->dev, "Failed to allocate iio device\n"); | ||
470 | return -ENOMEM; | ||
471 | } | ||
472 | |||
473 | st = iio_priv(indio_dev); | ||
474 | spi_set_drvdata(spi, indio_dev); | ||
475 | |||
476 | st->chip_info = &ad5360_chip_info_tbl[type]; | ||
477 | st->spi = spi; | ||
478 | |||
479 | indio_dev->dev.parent = &spi->dev; | ||
480 | indio_dev->name = spi_get_device_id(spi)->name; | ||
481 | indio_dev->info = &ad5360_info; | ||
482 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
483 | indio_dev->num_channels = st->chip_info->num_channels; | ||
484 | |||
485 | ret = ad5360_alloc_channels(indio_dev); | ||
486 | if (ret) { | ||
487 | dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret); | ||
488 | goto error_free; | ||
489 | } | ||
490 | |||
491 | for (i = 0; i < st->chip_info->num_vrefs; ++i) | ||
492 | st->vref_reg[i].supply = ad5360_vref_name[i]; | ||
493 | |||
494 | ret = regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs, | ||
495 | st->vref_reg); | ||
496 | if (ret) { | ||
497 | dev_err(&spi->dev, "Failed to request vref regulators: %d\n", ret); | ||
498 | goto error_free_channels; | ||
499 | } | ||
500 | |||
501 | ret = regulator_bulk_enable(st->chip_info->num_vrefs, st->vref_reg); | ||
502 | if (ret) { | ||
503 | dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", ret); | ||
504 | goto error_free_reg; | ||
505 | } | ||
506 | |||
507 | ret = iio_device_register(indio_dev); | ||
508 | if (ret) { | ||
509 | dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); | ||
510 | goto error_disable_reg; | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | |||
515 | error_disable_reg: | ||
516 | regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); | ||
517 | error_free_reg: | ||
518 | regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); | ||
519 | error_free_channels: | ||
520 | kfree(indio_dev->channels); | ||
521 | error_free: | ||
522 | iio_device_free(indio_dev); | ||
523 | |||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static int __devexit ad5360_remove(struct spi_device *spi) | ||
528 | { | ||
529 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
530 | struct ad5360_state *st = iio_priv(indio_dev); | ||
531 | |||
532 | iio_device_unregister(indio_dev); | ||
533 | |||
534 | kfree(indio_dev->channels); | ||
535 | |||
536 | regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); | ||
537 | regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); | ||
538 | |||
539 | iio_device_free(indio_dev); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static const struct spi_device_id ad5360_ids[] = { | ||
545 | { "ad5360", ID_AD5360 }, | ||
546 | { "ad5361", ID_AD5361 }, | ||
547 | { "ad5362", ID_AD5362 }, | ||
548 | { "ad5363", ID_AD5363 }, | ||
549 | { "ad5370", ID_AD5370 }, | ||
550 | { "ad5371", ID_AD5371 }, | ||
551 | { "ad5372", ID_AD5372 }, | ||
552 | { "ad5373", ID_AD5373 }, | ||
553 | {} | ||
554 | }; | ||
555 | MODULE_DEVICE_TABLE(spi, ad5360_ids); | ||
556 | |||
557 | static struct spi_driver ad5360_driver = { | ||
558 | .driver = { | ||
559 | .name = "ad5360", | ||
560 | .owner = THIS_MODULE, | ||
561 | }, | ||
562 | .probe = ad5360_probe, | ||
563 | .remove = __devexit_p(ad5360_remove), | ||
564 | .id_table = ad5360_ids, | ||
565 | }; | ||
566 | module_spi_driver(ad5360_driver); | ||
567 | |||
568 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
569 | MODULE_DESCRIPTION("Analog Devices AD5360/61/62/63/70/71/72/73 DAC"); | ||
570 | MODULE_LICENSE("GPL v2"); | ||