diff options
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/dac/Kconfig | 8 | ||||
-rw-r--r-- | drivers/iio/dac/ad5064.c | 200 |
2 files changed, 173 insertions, 35 deletions
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index afd207e171cf..1be15fa9d618 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig | |||
@@ -4,12 +4,12 @@ | |||
4 | menu "Digital to analog converters" | 4 | menu "Digital to analog converters" |
5 | 5 | ||
6 | config AD5064 | 6 | config AD5064 |
7 | tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/66/68 DAC driver" | 7 | tristate "Analog Devices AD5064 and similar multi-channel DAC driver" |
8 | depends on SPI | 8 | depends on (SPI_MASTER || I2C) |
9 | help | 9 | help |
10 | Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, | 10 | Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, |
11 | AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5666, AD5668 Digital | 11 | AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668, |
12 | to Analog Converter. | 12 | AD5669R Digital to Analog Converter. |
13 | 13 | ||
14 | To compile this driver as a module, choose M here: the | 14 | To compile this driver as a module, choose M here: the |
15 | module will be called ad5064. | 15 | module will be called ad5064. |
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 276af02520af..aa739c497f2b 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, | 2 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, |
3 | * AD5666, AD5668 Digital to analog converters driver | 3 | * AD5648, AD5666, AD5668, AD5669R Digital to analog converters driver |
4 | * | 4 | * |
5 | * Copyright 2011 Analog Devices Inc. | 5 | * Copyright 2011 Analog Devices Inc. |
6 | * | 6 | * |
@@ -12,9 +12,11 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/spi/spi.h> | 14 | #include <linux/spi/spi.h> |
15 | #include <linux/i2c.h> | ||
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
17 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
19 | #include <asm/unaligned.h> | ||
18 | 20 | ||
19 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
20 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
@@ -62,9 +64,14 @@ struct ad5064_chip_info { | |||
62 | unsigned int num_channels; | 64 | unsigned int num_channels; |
63 | }; | 65 | }; |
64 | 66 | ||
67 | struct ad5064_state; | ||
68 | |||
69 | typedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd, | ||
70 | unsigned int addr, unsigned int val); | ||
71 | |||
65 | /** | 72 | /** |
66 | * struct ad5064_state - driver instance specific data | 73 | * struct ad5064_state - driver instance specific data |
67 | * @spi: spi_device | 74 | * @dev: the device for this driver instance |
68 | * @chip_info: chip model specific constants, available modes etc | 75 | * @chip_info: chip model specific constants, available modes etc |
69 | * @vref_reg: vref supply regulators | 76 | * @vref_reg: vref supply regulators |
70 | * @pwr_down: whether channel is powered down | 77 | * @pwr_down: whether channel is powered down |
@@ -72,11 +79,12 @@ struct ad5064_chip_info { | |||
72 | * @dac_cache: current DAC raw value (chip does not support readback) | 79 | * @dac_cache: current DAC raw value (chip does not support readback) |
73 | * @use_internal_vref: set to true if the internal reference voltage should be | 80 | * @use_internal_vref: set to true if the internal reference voltage should be |
74 | * used. | 81 | * used. |
75 | * @data: spi transfer buffers | 82 | * @write: register write callback |
83 | * @data: i2c/spi transfer buffers | ||
76 | */ | 84 | */ |
77 | 85 | ||
78 | struct ad5064_state { | 86 | struct ad5064_state { |
79 | struct spi_device *spi; | 87 | struct device *dev; |
80 | const struct ad5064_chip_info *chip_info; | 88 | const struct ad5064_chip_info *chip_info; |
81 | struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; | 89 | struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; |
82 | bool pwr_down[AD5064_MAX_DAC_CHANNELS]; | 90 | bool pwr_down[AD5064_MAX_DAC_CHANNELS]; |
@@ -84,11 +92,16 @@ struct ad5064_state { | |||
84 | unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; | 92 | unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; |
85 | bool use_internal_vref; | 93 | bool use_internal_vref; |
86 | 94 | ||
95 | ad5064_write_func write; | ||
96 | |||
87 | /* | 97 | /* |
88 | * DMA (thus cache coherency maintenance) requires the | 98 | * DMA (thus cache coherency maintenance) requires the |
89 | * transfer buffers to live in their own cache lines. | 99 | * transfer buffers to live in their own cache lines. |
90 | */ | 100 | */ |
91 | __be32 data ____cacheline_aligned; | 101 | union { |
102 | u8 i2c[3]; | ||
103 | __be32 spi; | ||
104 | } data ____cacheline_aligned; | ||
92 | }; | 105 | }; |
93 | 106 | ||
94 | enum ad5064_type { | 107 | enum ad5064_type { |
@@ -109,14 +122,31 @@ enum ad5064_type { | |||
109 | ID_AD5668_2, | 122 | ID_AD5668_2, |
110 | }; | 123 | }; |
111 | 124 | ||
125 | static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, | ||
126 | unsigned int addr, unsigned int val) | ||
127 | { | ||
128 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
129 | |||
130 | st->data.i2c[0] = (cmd << 4) | addr; | ||
131 | put_unaligned_be16(val, &st->data.i2c[1]); | ||
132 | return i2c_master_send(i2c, st->data.i2c, 3); | ||
133 | } | ||
134 | |||
112 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, | 135 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, |
136 | unsigned int addr, unsigned int val) | ||
137 | { | ||
138 | struct spi_device *spi = to_spi_device(st->dev); | ||
139 | |||
140 | st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); | ||
141 | return spi_write(spi, &st->data.spi, sizeof(st->data.spi)); | ||
142 | } | ||
143 | |||
144 | static int ad5064_write(struct ad5064_state *st, unsigned int cmd, | ||
113 | unsigned int addr, unsigned int val, unsigned int shift) | 145 | unsigned int addr, unsigned int val, unsigned int shift) |
114 | { | 146 | { |
115 | val <<= shift; | 147 | val <<= shift; |
116 | 148 | ||
117 | st->data = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); | 149 | return st->write(st, cmd, addr, val); |
118 | |||
119 | return spi_write(st->spi, &st->data, sizeof(st->data)); | ||
120 | } | 150 | } |
121 | 151 | ||
122 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, | 152 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, |
@@ -130,7 +160,7 @@ static int ad5064_sync_powerdown_mode(struct ad5064_state *st, | |||
130 | if (st->pwr_down[channel]) | 160 | if (st->pwr_down[channel]) |
131 | val |= st->pwr_down_mode[channel] << 8; | 161 | val |= st->pwr_down_mode[channel] << 8; |
132 | 162 | ||
133 | ret = ad5064_spi_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); | 163 | ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); |
134 | 164 | ||
135 | return ret; | 165 | return ret; |
136 | } | 166 | } |
@@ -251,7 +281,7 @@ static int ad5064_write_raw(struct iio_dev *indio_dev, | |||
251 | return -EINVAL; | 281 | return -EINVAL; |
252 | 282 | ||
253 | mutex_lock(&indio_dev->mlock); | 283 | mutex_lock(&indio_dev->mlock); |
254 | ret = ad5064_spi_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, | 284 | ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, |
255 | chan->address, val, chan->scan_type.shift); | 285 | chan->address, val, chan->scan_type.shift); |
256 | if (ret == 0) | 286 | if (ret == 0) |
257 | st->dac_cache[chan->channel] = val; | 287 | st->dac_cache[chan->channel] = val; |
@@ -413,9 +443,9 @@ static const char * const ad5064_vref_name(struct ad5064_state *st, | |||
413 | return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; | 443 | return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; |
414 | } | 444 | } |
415 | 445 | ||
416 | static int __devinit ad5064_probe(struct spi_device *spi) | 446 | static int __devinit ad5064_probe(struct device *dev, enum ad5064_type type, |
447 | const char *name, ad5064_write_func write) | ||
417 | { | 448 | { |
418 | enum ad5064_type type = spi_get_device_id(spi)->driver_data; | ||
419 | struct iio_dev *indio_dev; | 449 | struct iio_dev *indio_dev; |
420 | struct ad5064_state *st; | 450 | struct ad5064_state *st; |
421 | unsigned int i; | 451 | unsigned int i; |
@@ -426,24 +456,25 @@ static int __devinit ad5064_probe(struct spi_device *spi) | |||
426 | return -ENOMEM; | 456 | return -ENOMEM; |
427 | 457 | ||
428 | st = iio_priv(indio_dev); | 458 | st = iio_priv(indio_dev); |
429 | spi_set_drvdata(spi, indio_dev); | 459 | dev_set_drvdata(dev, indio_dev); |
430 | 460 | ||
431 | st->chip_info = &ad5064_chip_info_tbl[type]; | 461 | st->chip_info = &ad5064_chip_info_tbl[type]; |
432 | st->spi = spi; | 462 | st->dev = dev; |
463 | st->write = write; | ||
433 | 464 | ||
434 | for (i = 0; i < ad5064_num_vref(st); ++i) | 465 | for (i = 0; i < ad5064_num_vref(st); ++i) |
435 | st->vref_reg[i].supply = ad5064_vref_name(st, i); | 466 | st->vref_reg[i].supply = ad5064_vref_name(st, i); |
436 | 467 | ||
437 | ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), | 468 | ret = regulator_bulk_get(dev, ad5064_num_vref(st), |
438 | st->vref_reg); | 469 | st->vref_reg); |
439 | if (ret) { | 470 | if (ret) { |
440 | if (!st->chip_info->internal_vref) | 471 | if (!st->chip_info->internal_vref) |
441 | goto error_free; | 472 | goto error_free; |
442 | st->use_internal_vref = true; | 473 | st->use_internal_vref = true; |
443 | ret = ad5064_spi_write(st, AD5064_CMD_CONFIG, 0, | 474 | ret = ad5064_write(st, AD5064_CMD_CONFIG, 0, |
444 | AD5064_CONFIG_INT_VREF_ENABLE, 0); | 475 | AD5064_CONFIG_INT_VREF_ENABLE, 0); |
445 | if (ret) { | 476 | if (ret) { |
446 | dev_err(&spi->dev, "Failed to enable internal vref: %d\n", | 477 | dev_err(dev, "Failed to enable internal vref: %d\n", |
447 | ret); | 478 | ret); |
448 | goto error_free; | 479 | goto error_free; |
449 | } | 480 | } |
@@ -458,8 +489,8 @@ static int __devinit ad5064_probe(struct spi_device *spi) | |||
458 | st->dac_cache[i] = 0x8000; | 489 | st->dac_cache[i] = 0x8000; |
459 | } | 490 | } |
460 | 491 | ||
461 | indio_dev->dev.parent = &spi->dev; | 492 | indio_dev->dev.parent = dev; |
462 | indio_dev->name = spi_get_device_id(spi)->name; | 493 | indio_dev->name = name; |
463 | indio_dev->info = &ad5064_info; | 494 | indio_dev->info = &ad5064_info; |
464 | indio_dev->modes = INDIO_DIRECT_MODE; | 495 | indio_dev->modes = INDIO_DIRECT_MODE; |
465 | indio_dev->channels = st->chip_info->channels; | 496 | indio_dev->channels = st->chip_info->channels; |
@@ -483,10 +514,9 @@ error_free: | |||
483 | return ret; | 514 | return ret; |
484 | } | 515 | } |
485 | 516 | ||
486 | 517 | static int __devexit ad5064_remove(struct device *dev) | |
487 | static int __devexit ad5064_remove(struct spi_device *spi) | ||
488 | { | 518 | { |
489 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 519 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
490 | struct ad5064_state *st = iio_priv(indio_dev); | 520 | struct ad5064_state *st = iio_priv(indio_dev); |
491 | 521 | ||
492 | iio_device_unregister(indio_dev); | 522 | iio_device_unregister(indio_dev); |
@@ -501,7 +531,22 @@ static int __devexit ad5064_remove(struct spi_device *spi) | |||
501 | return 0; | 531 | return 0; |
502 | } | 532 | } |
503 | 533 | ||
504 | static const struct spi_device_id ad5064_id[] = { | 534 | #if IS_ENABLED(CONFIG_SPI_MASTER) |
535 | |||
536 | static int __devinit ad5064_spi_probe(struct spi_device *spi) | ||
537 | { | ||
538 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
539 | |||
540 | return ad5064_probe(&spi->dev, id->driver_data, id->name, | ||
541 | ad5064_spi_write); | ||
542 | } | ||
543 | |||
544 | static int __devexit ad5064_spi_remove(struct spi_device *spi) | ||
545 | { | ||
546 | return ad5064_remove(&spi->dev); | ||
547 | } | ||
548 | |||
549 | static const struct spi_device_id ad5064_spi_ids[] = { | ||
505 | {"ad5024", ID_AD5024}, | 550 | {"ad5024", ID_AD5024}, |
506 | {"ad5025", ID_AD5025}, | 551 | {"ad5025", ID_AD5025}, |
507 | {"ad5044", ID_AD5044}, | 552 | {"ad5044", ID_AD5044}, |
@@ -520,19 +565,112 @@ static const struct spi_device_id ad5064_id[] = { | |||
520 | {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ | 565 | {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ |
521 | {} | 566 | {} |
522 | }; | 567 | }; |
523 | MODULE_DEVICE_TABLE(spi, ad5064_id); | 568 | MODULE_DEVICE_TABLE(spi, ad5064_spi_ids); |
524 | 569 | ||
525 | static struct spi_driver ad5064_driver = { | 570 | static struct spi_driver ad5064_spi_driver = { |
526 | .driver = { | 571 | .driver = { |
527 | .name = "ad5064", | 572 | .name = "ad5064", |
528 | .owner = THIS_MODULE, | 573 | .owner = THIS_MODULE, |
529 | }, | 574 | }, |
530 | .probe = ad5064_probe, | 575 | .probe = ad5064_spi_probe, |
531 | .remove = __devexit_p(ad5064_remove), | 576 | .remove = __devexit_p(ad5064_spi_remove), |
532 | .id_table = ad5064_id, | 577 | .id_table = ad5064_spi_ids, |
533 | }; | 578 | }; |
534 | module_spi_driver(ad5064_driver); | 579 | |
580 | static int __init ad5064_spi_register_driver(void) | ||
581 | { | ||
582 | return spi_register_driver(&ad5064_spi_driver); | ||
583 | } | ||
584 | |||
585 | static void __exit ad5064_spi_unregister_driver(void) | ||
586 | { | ||
587 | spi_unregister_driver(&ad5064_spi_driver); | ||
588 | } | ||
589 | |||
590 | #else | ||
591 | |||
592 | static inline int ad5064_spi_register_driver(void) { return 0; } | ||
593 | static inline void ad5064_spi_unregister_driver(void) { } | ||
594 | |||
595 | #endif | ||
596 | |||
597 | #if IS_ENABLED(CONFIG_I2C) | ||
598 | |||
599 | static int __devinit ad5064_i2c_probe(struct i2c_client *i2c, | ||
600 | const struct i2c_device_id *id) | ||
601 | { | ||
602 | return ad5064_probe(&i2c->dev, id->driver_data, id->name, | ||
603 | ad5064_i2c_write); | ||
604 | } | ||
605 | |||
606 | static int __devexit ad5064_i2c_remove(struct i2c_client *i2c) | ||
607 | { | ||
608 | return ad5064_remove(&i2c->dev); | ||
609 | } | ||
610 | |||
611 | static const struct i2c_device_id ad5064_i2c_ids[] = { | ||
612 | {"ad5629-1", ID_AD5628_1}, | ||
613 | {"ad5629-2", ID_AD5628_2}, | ||
614 | {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */ | ||
615 | {"ad5669-1", ID_AD5668_1}, | ||
616 | {"ad5669-2", ID_AD5668_2}, | ||
617 | {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */ | ||
618 | {} | ||
619 | }; | ||
620 | MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); | ||
621 | |||
622 | static struct i2c_driver ad5064_i2c_driver = { | ||
623 | .driver = { | ||
624 | .name = "ad5064", | ||
625 | .owner = THIS_MODULE, | ||
626 | }, | ||
627 | .probe = ad5064_i2c_probe, | ||
628 | .remove = __devexit_p(ad5064_i2c_remove), | ||
629 | .id_table = ad5064_i2c_ids, | ||
630 | }; | ||
631 | |||
632 | static int __init ad5064_i2c_register_driver(void) | ||
633 | { | ||
634 | return i2c_add_driver(&ad5064_i2c_driver); | ||
635 | } | ||
636 | |||
637 | static void __exit ad5064_i2c_unregister_driver(void) | ||
638 | { | ||
639 | i2c_del_driver(&ad5064_i2c_driver); | ||
640 | } | ||
641 | |||
642 | #else | ||
643 | |||
644 | static inline int ad5064_i2c_register_driver(void) { return 0; } | ||
645 | static inline void ad5064_i2c_unregister_driver(void) { } | ||
646 | |||
647 | #endif | ||
648 | |||
649 | static int __init ad5064_init(void) | ||
650 | { | ||
651 | int ret; | ||
652 | |||
653 | ret = ad5064_spi_register_driver(); | ||
654 | if (ret) | ||
655 | return ret; | ||
656 | |||
657 | ret = ad5064_i2c_register_driver(); | ||
658 | if (ret) { | ||
659 | ad5064_spi_unregister_driver(); | ||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | module_init(ad5064_init); | ||
666 | |||
667 | static void __exit ad5064_exit(void) | ||
668 | { | ||
669 | ad5064_i2c_unregister_driver(); | ||
670 | ad5064_spi_unregister_driver(); | ||
671 | } | ||
672 | module_exit(ad5064_exit); | ||
535 | 673 | ||
536 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 674 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
537 | MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/66/68 DAC"); | 675 | MODULE_DESCRIPTION("Analog Devices AD5024 and similar multi-channel DACs"); |
538 | MODULE_LICENSE("GPL v2"); | 676 | MODULE_LICENSE("GPL v2"); |