aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Francois Dagenais <jeff.dagenais@gmail.com>2012-08-21 10:28:00 -0400
committerJonathan Cameron <jic23@kernel.org>2012-09-03 15:26:45 -0400
commit3ec36a2cf0d50db61e15c6ee77d1dcdc73a7aca5 (patch)
tree1daedd6512f5e397c05a47354c592a929bc341cd
parente58bf5332d8ccc14ae0788e5541d4b8327728f5b (diff)
iio:ad5446: Add support for I2C based DACs
This patch adds support for I2C based single channel DACs to the ad5446 driver. Specifically AD5602, AD5612 and AD5622. V1: from Lars-Peter Clausen <lars@metafoo.de> V2: Split the device IDs into two enums and move them to the c file. Signed-off-by: Jean-Francois Dagenais <jeff.dagenais@gmail.com> Acked-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/dac/Kconfig9
-rw-r--r--drivers/iio/dac/ad5446.c402
-rw-r--r--drivers/iio/dac/ad5446.h29
3 files changed, 293 insertions, 147 deletions
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 1be15fa9d61..293b61dcc55 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -57,11 +57,12 @@ config AD5624R_SPI
57 57
58config AD5446 58config AD5446
59 tristate "Analog Devices AD5446 and similar single channel DACs driver" 59 tristate "Analog Devices AD5446 and similar single channel DACs driver"
60 depends on SPI 60 depends on (SPI_MASTER || I2C)
61 help 61 help
62 Say yes here to build support for Analog Devices AD5444, AD5446, AD5450, 62 Say yes here to build support for Analog Devices AD5602, AD5612, AD5622,
63 AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, 63 AD5444, AD5446, AD5450, AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A,
64 AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs. 64 AD5543, AD5553, AD5601, AD5611, AD5620, AD5621, AD5640, AD5660, AD5662
65 DACs.
65 66
66 To compile this driver as a module, choose M here: the 67 To compile this driver as a module, choose M here: the
67 module will be called ad5446. 68 module will be called ad5446.
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 2ca5059ef89..241665b8183 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -14,6 +14,7 @@
14#include <linux/sysfs.h> 14#include <linux/sysfs.h>
15#include <linux/list.h> 15#include <linux/list.h>
16#include <linux/spi/spi.h> 16#include <linux/spi/spi.h>
17#include <linux/i2c.h>
17#include <linux/regulator/consumer.h> 18#include <linux/regulator/consumer.h>
18#include <linux/err.h> 19#include <linux/err.h>
19#include <linux/module.h> 20#include <linux/module.h>
@@ -23,23 +24,6 @@
23 24
24#include "ad5446.h" 25#include "ad5446.h"
25 26
26static int ad5446_write(struct ad5446_state *st, unsigned val)
27{
28 __be16 data = cpu_to_be16(val);
29 return spi_write(st->spi, &data, sizeof(data));
30}
31
32static int ad5660_write(struct ad5446_state *st, unsigned val)
33{
34 uint8_t data[3];
35
36 data[0] = (val >> 16) & 0xFF;
37 data[1] = (val >> 8) & 0xFF;
38 data[2] = val & 0xFF;
39
40 return spi_write(st->spi, data, sizeof(data));
41}
42
43static const char * const ad5446_powerdown_modes[] = { 27static const char * const ad5446_powerdown_modes[] = {
44 "1kohm_to_gnd", "100kohm_to_gnd", "three_state" 28 "1kohm_to_gnd", "100kohm_to_gnd", "three_state"
45}; 29};
@@ -110,7 +94,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
110 return ret ? ret : len; 94 return ret ? ret : len;
111} 95}
112 96
113static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = { 97static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
114 { 98 {
115 .name = "powerdown", 99 .name = "powerdown",
116 .read = ad5446_read_dac_powerdown, 100 .read = ad5446_read_dac_powerdown,
@@ -136,84 +120,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
136 _AD5446_CHANNEL(bits, storage, shift, NULL) 120 _AD5446_CHANNEL(bits, storage, shift, NULL)
137 121
138#define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \ 122#define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
139 _AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown) 123 _AD5446_CHANNEL(bits, storage, shift, ad5446_ext_info_powerdown)
140
141static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
142 [ID_AD5444] = {
143 .channel = AD5446_CHANNEL(12, 16, 2),
144 .write = ad5446_write,
145 },
146 [ID_AD5446] = {
147 .channel = AD5446_CHANNEL(14, 16, 0),
148 .write = ad5446_write,
149 },
150 [ID_AD5450] = {
151 .channel = AD5446_CHANNEL(8, 16, 6),
152 .write = ad5446_write,
153 },
154 [ID_AD5451] = {
155 .channel = AD5446_CHANNEL(10, 16, 4),
156 .write = ad5446_write,
157 },
158 [ID_AD5541A] = {
159 .channel = AD5446_CHANNEL(16, 16, 0),
160 .write = ad5446_write,
161 },
162 [ID_AD5512A] = {
163 .channel = AD5446_CHANNEL(12, 16, 4),
164 .write = ad5446_write,
165 },
166 [ID_AD5553] = {
167 .channel = AD5446_CHANNEL(14, 16, 0),
168 .write = ad5446_write,
169 },
170 [ID_AD5601] = {
171 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
172 .write = ad5446_write,
173 },
174 [ID_AD5611] = {
175 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
176 .write = ad5446_write,
177 },
178 [ID_AD5621] = {
179 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
180 .write = ad5446_write,
181 },
182 [ID_AD5620_2500] = {
183 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
184 .int_vref_mv = 2500,
185 .write = ad5446_write,
186 },
187 [ID_AD5620_1250] = {
188 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
189 .int_vref_mv = 1250,
190 .write = ad5446_write,
191 },
192 [ID_AD5640_2500] = {
193 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
194 .int_vref_mv = 2500,
195 .write = ad5446_write,
196 },
197 [ID_AD5640_1250] = {
198 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
199 .int_vref_mv = 1250,
200 .write = ad5446_write,
201 },
202 [ID_AD5660_2500] = {
203 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
204 .int_vref_mv = 2500,
205 .write = ad5660_write,
206 },
207 [ID_AD5660_1250] = {
208 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
209 .int_vref_mv = 1250,
210 .write = ad5660_write,
211 },
212 [ID_AD5662] = {
213 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
214 .write = ad5660_write,
215 },
216};
217 124
218static int ad5446_read_raw(struct iio_dev *indio_dev, 125static int ad5446_read_raw(struct iio_dev *indio_dev,
219 struct iio_chan_spec const *chan, 126 struct iio_chan_spec const *chan,
@@ -272,14 +179,15 @@ static const struct iio_info ad5446_info = {
272 .driver_module = THIS_MODULE, 179 .driver_module = THIS_MODULE,
273}; 180};
274 181
275static int __devinit ad5446_probe(struct spi_device *spi) 182static int __devinit ad5446_probe(struct device *dev, const char *name,
183 const struct ad5446_chip_info *chip_info)
276{ 184{
277 struct ad5446_state *st; 185 struct ad5446_state *st;
278 struct iio_dev *indio_dev; 186 struct iio_dev *indio_dev;
279 struct regulator *reg; 187 struct regulator *reg;
280 int ret, voltage_uv = 0; 188 int ret, voltage_uv = 0;
281 189
282 reg = regulator_get(&spi->dev, "vcc"); 190 reg = regulator_get(dev, "vcc");
283 if (!IS_ERR(reg)) { 191 if (!IS_ERR(reg)) {
284 ret = regulator_enable(reg); 192 ret = regulator_enable(reg);
285 if (ret) 193 if (ret)
@@ -294,16 +202,15 @@ static int __devinit ad5446_probe(struct spi_device *spi)
294 goto error_disable_reg; 202 goto error_disable_reg;
295 } 203 }
296 st = iio_priv(indio_dev); 204 st = iio_priv(indio_dev);
297 st->chip_info = 205 st->chip_info = chip_info;
298 &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
299 206
300 spi_set_drvdata(spi, indio_dev); 207 dev_set_drvdata(dev, indio_dev);
301 st->reg = reg; 208 st->reg = reg;
302 st->spi = spi; 209 st->dev = dev;
303 210
304 /* Establish that the iio_dev is a child of the spi device */ 211 /* Establish that the iio_dev is a child of the device */
305 indio_dev->dev.parent = &spi->dev; 212 indio_dev->dev.parent = dev;
306 indio_dev->name = spi_get_device_id(spi)->name; 213 indio_dev->name = name;
307 indio_dev->info = &ad5446_info; 214 indio_dev->info = &ad5446_info;
308 indio_dev->modes = INDIO_DIRECT_MODE; 215 indio_dev->modes = INDIO_DIRECT_MODE;
309 indio_dev->channels = &st->chip_info->channel; 216 indio_dev->channels = &st->chip_info->channel;
@@ -316,7 +223,7 @@ static int __devinit ad5446_probe(struct spi_device *spi)
316 else if (voltage_uv) 223 else if (voltage_uv)
317 st->vref_mv = voltage_uv / 1000; 224 st->vref_mv = voltage_uv / 1000;
318 else 225 else
319 dev_warn(&spi->dev, "reference voltage unspecified\n"); 226 dev_warn(dev, "reference voltage unspecified\n");
320 227
321 ret = iio_device_register(indio_dev); 228 ret = iio_device_register(indio_dev);
322 if (ret) 229 if (ret)
@@ -336,9 +243,9 @@ error_put_reg:
336 return ret; 243 return ret;
337} 244}
338 245
339static int ad5446_remove(struct spi_device *spi) 246static int ad5446_remove(struct device *dev)
340{ 247{
341 struct iio_dev *indio_dev = spi_get_drvdata(spi); 248 struct iio_dev *indio_dev = dev_get_drvdata(dev);
342 struct ad5446_state *st = iio_priv(indio_dev); 249 struct ad5446_state *st = iio_priv(indio_dev);
343 250
344 iio_device_unregister(indio_dev); 251 iio_device_unregister(indio_dev);
@@ -351,7 +258,133 @@ static int ad5446_remove(struct spi_device *spi)
351 return 0; 258 return 0;
352} 259}
353 260
354static const struct spi_device_id ad5446_id[] = { 261#if IS_ENABLED(CONFIG_SPI_MASTER)
262
263static int ad5446_write(struct ad5446_state *st, unsigned val)
264{
265 struct spi_device *spi = to_spi_device(st->dev);
266 __be16 data = cpu_to_be16(val);
267
268 return spi_write(spi, &data, sizeof(data));
269}
270
271static int ad5660_write(struct ad5446_state *st, unsigned val)
272{
273 struct spi_device *spi = to_spi_device(st->dev);
274 uint8_t data[3];
275
276 data[0] = (val >> 16) & 0xFF;
277 data[1] = (val >> 8) & 0xFF;
278 data[2] = val & 0xFF;
279
280 return spi_write(spi, data, sizeof(data));
281}
282
283/**
284 * ad5446_supported_spi_device_ids:
285 * The AD5620/40/60 parts are available in different fixed internal reference
286 * voltage options. The actual part numbers may look differently
287 * (and a bit cryptic), however this style is used to make clear which
288 * parts are supported here.
289 */
290enum ad5446_supported_spi_device_ids {
291 ID_AD5444,
292 ID_AD5446,
293 ID_AD5450,
294 ID_AD5451,
295 ID_AD5541A,
296 ID_AD5512A,
297 ID_AD5553,
298 ID_AD5601,
299 ID_AD5611,
300 ID_AD5621,
301 ID_AD5620_2500,
302 ID_AD5620_1250,
303 ID_AD5640_2500,
304 ID_AD5640_1250,
305 ID_AD5660_2500,
306 ID_AD5660_1250,
307 ID_AD5662,
308};
309
310static const struct ad5446_chip_info ad5446_spi_chip_info[] = {
311 [ID_AD5444] = {
312 .channel = AD5446_CHANNEL(12, 16, 2),
313 .write = ad5446_write,
314 },
315 [ID_AD5446] = {
316 .channel = AD5446_CHANNEL(14, 16, 0),
317 .write = ad5446_write,
318 },
319 [ID_AD5450] = {
320 .channel = AD5446_CHANNEL(8, 16, 6),
321 .write = ad5446_write,
322 },
323 [ID_AD5451] = {
324 .channel = AD5446_CHANNEL(10, 16, 4),
325 .write = ad5446_write,
326 },
327 [ID_AD5541A] = {
328 .channel = AD5446_CHANNEL(16, 16, 0),
329 .write = ad5446_write,
330 },
331 [ID_AD5512A] = {
332 .channel = AD5446_CHANNEL(12, 16, 4),
333 .write = ad5446_write,
334 },
335 [ID_AD5553] = {
336 .channel = AD5446_CHANNEL(14, 16, 0),
337 .write = ad5446_write,
338 },
339 [ID_AD5601] = {
340 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
341 .write = ad5446_write,
342 },
343 [ID_AD5611] = {
344 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
345 .write = ad5446_write,
346 },
347 [ID_AD5621] = {
348 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
349 .write = ad5446_write,
350 },
351 [ID_AD5620_2500] = {
352 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
353 .int_vref_mv = 2500,
354 .write = ad5446_write,
355 },
356 [ID_AD5620_1250] = {
357 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
358 .int_vref_mv = 1250,
359 .write = ad5446_write,
360 },
361 [ID_AD5640_2500] = {
362 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
363 .int_vref_mv = 2500,
364 .write = ad5446_write,
365 },
366 [ID_AD5640_1250] = {
367 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
368 .int_vref_mv = 1250,
369 .write = ad5446_write,
370 },
371 [ID_AD5660_2500] = {
372 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
373 .int_vref_mv = 2500,
374 .write = ad5660_write,
375 },
376 [ID_AD5660_1250] = {
377 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
378 .int_vref_mv = 1250,
379 .write = ad5660_write,
380 },
381 [ID_AD5662] = {
382 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
383 .write = ad5660_write,
384 },
385};
386
387static const struct spi_device_id ad5446_spi_ids[] = {
355 {"ad5444", ID_AD5444}, 388 {"ad5444", ID_AD5444},
356 {"ad5446", ID_AD5446}, 389 {"ad5446", ID_AD5446},
357 {"ad5450", ID_AD5450}, 390 {"ad5450", ID_AD5450},
@@ -375,18 +408,157 @@ static const struct spi_device_id ad5446_id[] = {
375 {"ad5662", ID_AD5662}, 408 {"ad5662", ID_AD5662},
376 {} 409 {}
377}; 410};
378MODULE_DEVICE_TABLE(spi, ad5446_id); 411MODULE_DEVICE_TABLE(spi, ad5446_spi_ids);
412
413static int __devinit ad5446_spi_probe(struct spi_device *spi)
414{
415 const struct spi_device_id *id = spi_get_device_id(spi);
416
417 return ad5446_probe(&spi->dev, id->name,
418 &ad5446_spi_chip_info[id->driver_data]);
419}
379 420
380static struct spi_driver ad5446_driver = { 421static int __devexit ad5446_spi_remove(struct spi_device *spi)
422{
423 return ad5446_remove(&spi->dev);
424}
425
426static struct spi_driver ad5446_spi_driver = {
381 .driver = { 427 .driver = {
382 .name = "ad5446", 428 .name = "ad5446",
383 .owner = THIS_MODULE, 429 .owner = THIS_MODULE,
384 }, 430 },
385 .probe = ad5446_probe, 431 .probe = ad5446_spi_probe,
386 .remove = __devexit_p(ad5446_remove), 432 .remove = __devexit_p(ad5446_spi_remove),
387 .id_table = ad5446_id, 433 .id_table = ad5446_spi_ids,
434};
435
436static int __init ad5446_spi_register_driver(void)
437{
438 return spi_register_driver(&ad5446_spi_driver);
439}
440
441static void ad5446_spi_unregister_driver(void)
442{
443 spi_unregister_driver(&ad5446_spi_driver);
444}
445
446#else
447
448static inline int ad5446_spi_register_driver(void) { return 0; }
449static inline void ad5446_spi_unregister_driver(void) { }
450
451#endif
452
453#if IS_ENABLED(CONFIG_I2C)
454
455static int ad5622_write(struct ad5446_state *st, unsigned val)
456{
457 struct i2c_client *client = to_i2c_client(st->dev);
458 __be16 data = cpu_to_be16(val);
459
460 return i2c_master_send(client, (char *)&data, sizeof(data));
461}
462
463/**
464 * ad5446_supported_i2c_device_ids:
465 * The AD5620/40/60 parts are available in different fixed internal reference
466 * voltage options. The actual part numbers may look differently
467 * (and a bit cryptic), however this style is used to make clear which
468 * parts are supported here.
469 */
470enum ad5446_supported_i2c_device_ids {
471 ID_AD5602,
472 ID_AD5612,
473 ID_AD5622,
474};
475
476static const struct ad5446_chip_info ad5446_i2c_chip_info[] = {
477 [ID_AD5602] = {
478 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
479 .write = ad5622_write,
480 },
481 [ID_AD5612] = {
482 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
483 .write = ad5622_write,
484 },
485 [ID_AD5622] = {
486 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
487 .write = ad5622_write,
488 },
388}; 489};
389module_spi_driver(ad5446_driver); 490
491static int __devinit ad5446_i2c_probe(struct i2c_client *i2c,
492 const struct i2c_device_id *id)
493{
494 return ad5446_probe(&i2c->dev, id->name,
495 &ad5446_i2c_chip_info[id->driver_data]);
496}
497
498static int __devexit ad5446_i2c_remove(struct i2c_client *i2c)
499{
500 return ad5446_remove(&i2c->dev);
501}
502
503static const struct i2c_device_id ad5446_i2c_ids[] = {
504 {"ad5602", ID_AD5602},
505 {"ad5612", ID_AD5612},
506 {"ad5622", ID_AD5622},
507 {}
508};
509MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids);
510
511static struct i2c_driver ad5446_i2c_driver = {
512 .driver = {
513 .name = "ad5446",
514 .owner = THIS_MODULE,
515 },
516 .probe = ad5446_i2c_probe,
517 .remove = __devexit_p(ad5446_i2c_remove),
518 .id_table = ad5446_i2c_ids,
519};
520
521static int __init ad5446_i2c_register_driver(void)
522{
523 return i2c_add_driver(&ad5446_i2c_driver);
524}
525
526static void __exit ad5446_i2c_unregister_driver(void)
527{
528 i2c_del_driver(&ad5446_i2c_driver);
529}
530
531#else
532
533static inline int ad5446_i2c_register_driver(void) { return 0; }
534static inline void ad5446_i2c_unregister_driver(void) { }
535
536#endif
537
538static int __init ad5446_init(void)
539{
540 int ret;
541
542 ret = ad5446_spi_register_driver();
543 if (ret)
544 return ret;
545
546 ret = ad5446_i2c_register_driver();
547 if (ret) {
548 ad5446_spi_unregister_driver();
549 return ret;
550 }
551
552 return 0;
553}
554module_init(ad5446_init);
555
556static void __exit ad5446_exit(void)
557{
558 ad5446_i2c_unregister_driver();
559 ad5446_spi_unregister_driver();
560}
561module_exit(ad5446_exit);
390 562
391MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 563MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
392MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC"); 564MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
diff --git a/drivers/iio/dac/ad5446.h b/drivers/iio/dac/ad5446.h
index 2934269a56d..6b7a1766c10 100644
--- a/drivers/iio/dac/ad5446.h
+++ b/drivers/iio/dac/ad5446.h
@@ -38,7 +38,7 @@
38 */ 38 */
39 39
40struct ad5446_state { 40struct ad5446_state {
41 struct spi_device *spi; 41 struct device *dev;
42 const struct ad5446_chip_info *chip_info; 42 const struct ad5446_chip_info *chip_info;
43 struct regulator *reg; 43 struct regulator *reg;
44 unsigned short vref_mv; 44 unsigned short vref_mv;
@@ -60,32 +60,5 @@ struct ad5446_chip_info {
60 int (*write)(struct ad5446_state *st, unsigned val); 60 int (*write)(struct ad5446_state *st, unsigned val);
61}; 61};
62 62
63/**
64 * ad5446_supported_device_ids:
65 * The AD5620/40/60 parts are available in different fixed internal reference
66 * voltage options. The actual part numbers may look differently
67 * (and a bit cryptic), however this style is used to make clear which
68 * parts are supported here.
69 */
70
71enum ad5446_supported_device_ids {
72 ID_AD5444,
73 ID_AD5446,
74 ID_AD5450,
75 ID_AD5451,
76 ID_AD5541A,
77 ID_AD5512A,
78 ID_AD5553,
79 ID_AD5601,
80 ID_AD5611,
81 ID_AD5621,
82 ID_AD5620_2500,
83 ID_AD5620_1250,
84 ID_AD5640_2500,
85 ID_AD5640_1250,
86 ID_AD5660_2500,
87 ID_AD5660_1250,
88 ID_AD5662,
89};
90 63
91#endif /* IIO_DAC_AD5446_H_ */ 64#endif /* IIO_DAC_AD5446_H_ */