From 78f585feed754c94f890cf94c1eed31ab11830c6 Mon Sep 17 00:00:00 2001 From: Marc Andre Date: Mon, 8 Feb 2016 18:01:46 +0100 Subject: iio:ad5064: Structural changes to support LTC2617 This patch makes minor structural changes to support specifics for LTC2617 DAC. This DAC requires different handling of the power down modes. The configuration to actually support the DAC will be submitted in a secondary patch. Adjust the DECLARE_AD5064_CHANNELS() macro to accept a new ext_info parameter. This allows to use different power down modes per DAC. (e.g. DAC only support 90kohm to ground) Add the chip_info parameter "powerdown_ltc". This parameter is used in the ad5064_sync_powerdown_mode() function to handle the power down command for LTC diffently. For those devices the power down command must be addressed to the channel. Signed-off-by: Marc Andre Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5064.c | 67 +++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 29 deletions(-) (limited to 'drivers/iio/dac/ad5064.c') diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 81ca0081a019..c55282d5e753 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -50,10 +50,12 @@ /** * struct ad5064_chip_info - chip specific information * @shared_vref: whether the vref supply is shared between channels - * @internal_vref: internal reference voltage. 0 if the chip has no internal - * vref. + * @internal_vref: internal reference voltage. 0 if the chip has no + internal vref. * @channel: channel specification * @num_channels: number of channels + * @powerdown_ltc: Use alternative power down addressing as required by + * ltc2617 and others. */ struct ad5064_chip_info { @@ -61,6 +63,7 @@ struct ad5064_chip_info { unsigned long internal_vref; const struct iio_chan_spec *channels; unsigned int num_channels; + bool powerdown_ltc; }; struct ad5064_state; @@ -136,15 +139,21 @@ static int ad5064_write(struct ad5064_state *st, unsigned int cmd, static int ad5064_sync_powerdown_mode(struct ad5064_state *st, const struct iio_chan_spec *chan) { - unsigned int val; + unsigned int val, address; int ret; - val = (0x1 << chan->address); + if (st->chip_info->powerdown_ltc) { + val = 0; + address = chan->address; + } else { + address = 0; + val = (0x1 << chan->address); - if (st->pwr_down[chan->channel]) - val |= st->pwr_down_mode[chan->channel] << 8; + if (st->pwr_down[chan->channel]) + val |= st->pwr_down_mode[chan->channel] << 8; + } - ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); + ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, address, val, 0); return ret; } @@ -295,7 +304,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { { }, }; -#define AD5064_CHANNEL(chan, addr, bits, _shift) { \ +#define AD5064_CHANNEL(chan, addr, bits, _shift, _ext_info) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .output = 1, \ @@ -309,37 +318,37 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { .storagebits = 16, \ .shift = (_shift), \ }, \ - .ext_info = ad5064_ext_info, \ + .ext_info = (_ext_info), \ } -#define DECLARE_AD5064_CHANNELS(name, bits, shift) \ +#define DECLARE_AD5064_CHANNELS(name, bits, shift, ext_info) \ const struct iio_chan_spec name[] = { \ - AD5064_CHANNEL(0, 0, bits, shift), \ - AD5064_CHANNEL(1, 1, bits, shift), \ - AD5064_CHANNEL(2, 2, bits, shift), \ - AD5064_CHANNEL(3, 3, bits, shift), \ - AD5064_CHANNEL(4, 4, bits, shift), \ - AD5064_CHANNEL(5, 5, bits, shift), \ - AD5064_CHANNEL(6, 6, bits, shift), \ - AD5064_CHANNEL(7, 7, bits, shift), \ + AD5064_CHANNEL(0, 0, bits, shift, ext_info), \ + AD5064_CHANNEL(1, 1, bits, shift, ext_info), \ + AD5064_CHANNEL(2, 2, bits, shift, ext_info), \ + AD5064_CHANNEL(3, 3, bits, shift, ext_info), \ + AD5064_CHANNEL(4, 4, bits, shift, ext_info), \ + AD5064_CHANNEL(5, 5, bits, shift, ext_info), \ + AD5064_CHANNEL(6, 6, bits, shift, ext_info), \ + AD5064_CHANNEL(7, 7, bits, shift, ext_info), \ } -#define DECLARE_AD5065_CHANNELS(name, bits, shift) \ +#define DECLARE_AD5065_CHANNELS(name, bits, shift, ext_info) \ const struct iio_chan_spec name[] = { \ - AD5064_CHANNEL(0, 0, bits, shift), \ - AD5064_CHANNEL(1, 3, bits, shift), \ + AD5064_CHANNEL(0, 0, bits, shift, ext_info), \ + AD5064_CHANNEL(1, 3, bits, shift, ext_info), \ } -static DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8); -static DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6); -static DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4); +static DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8, ad5064_ext_info); +static DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6, ad5064_ext_info); +static DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4, ad5064_ext_info); -static DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8); -static DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6); -static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4); +static DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8, ad5064_ext_info); +static DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6, ad5064_ext_info); +static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4, ad5064_ext_info); -static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4); -static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0); +static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4, ad5064_ext_info); +static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info); static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { [ID_AD5024] = { -- cgit v1.2.3 From 8d144c9608a6efb62b2a53f81e1bbe4f6c1d0e78 Mon Sep 17 00:00:00 2001 From: Marc Andre Date: Mon, 8 Feb 2016 18:01:47 +0100 Subject: iio:ad5064: Add support for ltc2617 and similar devices The Linear Technology LTC2606, LTC2607, LTC2609, LTC2616, LTC2617, LTC2619, LTC2626, LTC2627 and LTC2629 devices are very similar to the AD5064 device. This patch adds support for those devices. Datasheet for LTC devices: LTC2606, LTC2616, LTC2626: http://www.linear.com/docs/6398 LTC2607, LTC2617, LTC2627: http://www.linear.com/docs/8977 LTC2709, LTC2619, LTC2629: http://www.linear.com/docs/8477 Signed-off-by: Marc Andre Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 1 + drivers/iio/dac/ad5064.c | 112 +++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) (limited to 'drivers/iio/dac/ad5064.c') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 80c6fce9935b..3c6624881375 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -496,6 +496,7 @@ Description: 1kohm_to_gnd: connected to ground via an 1kOhm resistor, 6kohm_to_gnd: connected to ground via a 6kOhm resistor, 20kohm_to_gnd: connected to ground via a 20kOhm resistor, + 90kohm_to_gnd: connected to ground via a 90kOhm resistor, 100kohm_to_gnd: connected to ground via an 100kOhm resistor, 125kohm_to_gnd: connected to ground via an 125kOhm resistor, 500kohm_to_gnd: connected to ground via a 500kOhm resistor, diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index c55282d5e753..7cc3e93a2aa6 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -1,6 +1,8 @@ /* * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, - * AD5648, AD5666, AD5668, AD5669R Digital to analog converters driver + * AD5648, AD5666, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, + * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to analog converters + * driver * * Copyright 2011 Analog Devices Inc. * @@ -126,6 +128,15 @@ enum ad5064_type { ID_AD5668_2, ID_AD5669_1, ID_AD5669_2, + ID_LTC2606, + ID_LTC2607, + ID_LTC2609, + ID_LTC2616, + ID_LTC2617, + ID_LTC2619, + ID_LTC2626, + ID_LTC2627, + ID_LTC2629, }; static int ad5064_write(struct ad5064_state *st, unsigned int cmd, @@ -164,6 +175,10 @@ static const char * const ad5064_powerdown_modes[] = { "three_state", }; +static const char * const ltc2617_powerdown_modes[] = { + "90kohm_to_gnd", +}; + static int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, const struct iio_chan_spec *chan) { @@ -194,6 +209,13 @@ static const struct iio_enum ad5064_powerdown_mode_enum = { .set = ad5064_set_powerdown_mode, }; +static const struct iio_enum ltc2617_powerdown_mode_enum = { + .items = ltc2617_powerdown_modes, + .num_items = ARRAY_SIZE(ltc2617_powerdown_modes), + .get = ad5064_get_powerdown_mode, + .set = ad5064_set_powerdown_mode, +}; + static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, char *buf) { @@ -304,6 +326,18 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { { }, }; +static const struct iio_chan_spec_ext_info ltc2617_ext_info[] = { + { + .name = "powerdown", + .read = ad5064_read_dac_powerdown, + .write = ad5064_write_dac_powerdown, + .shared = IIO_SEPARATE, + }, + IIO_ENUM("powerdown_mode", IIO_SEPARATE, <c2617_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", <c2617_powerdown_mode_enum), + { }, +}; + #define AD5064_CHANNEL(chan, addr, bits, _shift, _ext_info) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -350,6 +384,10 @@ static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4, ad5064_ext_info); static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4, ad5064_ext_info); static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info); +static DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info); +static DECLARE_AD5064_CHANNELS(ltc2617_channels, 14, 2, ltc2617_ext_info); +static DECLARE_AD5064_CHANNELS(ltc2627_channels, 12, 4, ltc2617_ext_info); + static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { [ID_AD5024] = { .shared_vref = false, @@ -458,6 +496,69 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .channels = ad5669_channels, .num_channels = 8, }, + [ID_LTC2606] = { + .shared_vref = true, + .internal_vref = 0, + .channels = ltc2607_channels, + .num_channels = 1, + .powerdown_ltc = true, + }, + [ID_LTC2607] = { + .shared_vref = true, + .internal_vref = 0, + .channels = ltc2607_channels, + .num_channels = 2, + .powerdown_ltc = true, + }, + [ID_LTC2609] = { + .shared_vref = false, + .internal_vref = 0, + .channels = ltc2607_channels, + .num_channels = 4, + .powerdown_ltc = true, + }, + [ID_LTC2616] = { + .shared_vref = true, + .internal_vref = 0, + .channels = ltc2617_channels, + .num_channels = 1, + .powerdown_ltc = true, + }, + [ID_LTC2617] = { + .shared_vref = true, + .internal_vref = 0, + .channels = ltc2617_channels, + .num_channels = 2, + .powerdown_ltc = true, + }, + [ID_LTC2619] = { + .shared_vref = false, + .internal_vref = 0, + .channels = ltc2617_channels, + .num_channels = 4, + .powerdown_ltc = true, + }, + [ID_LTC2626] = { + .shared_vref = true, + .internal_vref = 0, + .channels = ltc2627_channels, + .num_channels = 1, + .powerdown_ltc = true, + }, + [ID_LTC2627] = { + .shared_vref = true, + .internal_vref = 0, + .channels = ltc2627_channels, + .num_channels = 2, + .powerdown_ltc = true, + }, + [ID_LTC2629] = { + .shared_vref = false, + .internal_vref = 0, + .channels = ltc2627_channels, + .num_channels = 4, + .powerdown_ltc = true, + }, }; static inline unsigned int ad5064_num_vref(struct ad5064_state *st) @@ -668,6 +769,15 @@ static const struct i2c_device_id ad5064_i2c_ids[] = { {"ad5669-1", ID_AD5669_1}, {"ad5669-2", ID_AD5669_2}, {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */ + {"ltc2606", ID_LTC2606}, + {"ltc2607", ID_LTC2607}, + {"ltc2609", ID_LTC2609}, + {"ltc2616", ID_LTC2616}, + {"ltc2617", ID_LTC2617}, + {"ltc2619", ID_LTC2619}, + {"ltc2626", ID_LTC2626}, + {"ltc2627", ID_LTC2627}, + {"ltc2629", ID_LTC2629}, {} }; MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); -- cgit v1.2.3 From 4946ff5858392012ed17a079c5b3dd4bc4b15cf9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 8 Feb 2016 18:01:49 +0100 Subject: iio:ad5064: Use a enum for the register map layout type Currently the ad5064 only supports two different register map variations and this is represented by a bool. This patch changes since to a enum so we can support more variations in the future. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5064.c | 54 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers/iio/dac/ad5064.c') diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 7cc3e93a2aa6..b7f717cadd0b 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -49,6 +49,16 @@ #define AD5064_LDAC_PWRDN_100K 0x2 #define AD5064_LDAC_PWRDN_3STATE 0x3 +/** + * enum ad5064_regmap_type - Register layout variant + * @AD5064_REGMAP_ADI: Analog Devices register map layout + * @AD5064_REGMAP_LTC: LTC register map layout + */ +enum ad5064_regmap_type { + AD5064_REGMAP_ADI, + AD5064_REGMAP_LTC, +}; + /** * struct ad5064_chip_info - chip specific information * @shared_vref: whether the vref supply is shared between channels @@ -56,8 +66,7 @@ internal vref. * @channel: channel specification * @num_channels: number of channels - * @powerdown_ltc: Use alternative power down addressing as required by - * ltc2617 and others. + * @regmap_type: register map layout variant */ struct ad5064_chip_info { @@ -65,7 +74,7 @@ struct ad5064_chip_info { unsigned long internal_vref; const struct iio_chan_spec *channels; unsigned int num_channels; - bool powerdown_ltc; + enum ad5064_regmap_type regmap_type; }; struct ad5064_state; @@ -153,7 +162,7 @@ static int ad5064_sync_powerdown_mode(struct ad5064_state *st, unsigned int val, address; int ret; - if (st->chip_info->powerdown_ltc) { + if (st->chip_info->regmap_type == AD5064_REGMAP_LTC) { val = 0; address = chan->address; } else { @@ -393,171 +402,190 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .shared_vref = false, .channels = ad5024_channels, .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5025] = { .shared_vref = false, .channels = ad5025_channels, .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5044] = { .shared_vref = false, .channels = ad5044_channels, .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5045] = { .shared_vref = false, .channels = ad5045_channels, .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5064] = { .shared_vref = false, .channels = ad5064_channels, .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5064_1] = { .shared_vref = true, .channels = ad5064_channels, .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5065] = { .shared_vref = false, .channels = ad5065_channels, .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5628_1] = { .shared_vref = true, .internal_vref = 2500000, .channels = ad5024_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5628_2] = { .shared_vref = true, .internal_vref = 5000000, .channels = ad5024_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5629_1] = { .shared_vref = true, .internal_vref = 2500000, .channels = ad5629_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5629_2] = { .shared_vref = true, .internal_vref = 5000000, .channels = ad5629_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5648_1] = { .shared_vref = true, .internal_vref = 2500000, .channels = ad5044_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5648_2] = { .shared_vref = true, .internal_vref = 5000000, .channels = ad5044_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5666_1] = { .shared_vref = true, .internal_vref = 2500000, .channels = ad5064_channels, .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5666_2] = { .shared_vref = true, .internal_vref = 5000000, .channels = ad5064_channels, .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5668_1] = { .shared_vref = true, .internal_vref = 2500000, .channels = ad5064_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5668_2] = { .shared_vref = true, .internal_vref = 5000000, .channels = ad5064_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5669_1] = { .shared_vref = true, .internal_vref = 2500000, .channels = ad5669_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_AD5669_2] = { .shared_vref = true, .internal_vref = 5000000, .channels = ad5669_channels, .num_channels = 8, + .regmap_type = AD5064_REGMAP_ADI, }, [ID_LTC2606] = { .shared_vref = true, .internal_vref = 0, .channels = ltc2607_channels, .num_channels = 1, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2607] = { .shared_vref = true, .internal_vref = 0, .channels = ltc2607_channels, .num_channels = 2, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2609] = { .shared_vref = false, .internal_vref = 0, .channels = ltc2607_channels, .num_channels = 4, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2616] = { .shared_vref = true, .internal_vref = 0, .channels = ltc2617_channels, .num_channels = 1, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2617] = { .shared_vref = true, .internal_vref = 0, .channels = ltc2617_channels, .num_channels = 2, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2619] = { .shared_vref = false, .internal_vref = 0, .channels = ltc2617_channels, .num_channels = 4, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2626] = { .shared_vref = true, .internal_vref = 0, .channels = ltc2627_channels, .num_channels = 1, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2627] = { .shared_vref = true, .internal_vref = 0, .channels = ltc2627_channels, .num_channels = 2, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, [ID_LTC2629] = { .shared_vref = false, .internal_vref = 0, .channels = ltc2627_channels, .num_channels = 4, - .powerdown_ltc = true, + .regmap_type = AD5064_REGMAP_LTC, }, }; -- cgit v1.2.3 From f47732c0daf5d1607ba0775edad3460d18ee1f83 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 8 Feb 2016 18:01:50 +0100 Subject: iio:ad5064: Add AD5625/AD5627/AD5645/AD5647/AD4665/AD5657 support The AD5625/AD5645/AD5665 are a family of 4 channel DACs with 12-bit, 14-bit and 16-bit precision respectively. The devices come in 3 flavors in terms of built-in reference, either no built-in reference, built-in 1.25V reference or built-in 2.5V reference. The AD5627/AD5647/AD5667 are similar to the AD5625/AD5645/AD5665 except that they have 2 instead of 4 channels. While these new devices are mostly register map compatible with the existing devices support by the driver some offsets and register addresses have been shuffled around. To accommodate this introduce a new register map layout. For the lack of a better name we will just call it version 2. Datasheets: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5625R_5645R_5665R_5625_5665.pdf http://www.analog.com/media/en/technical-documentation/data-sheets/AD5627R_5647R_5667R_5627_5667.pdf Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/Kconfig | 7 +- drivers/iio/dac/ad5064.c | 192 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 188 insertions(+), 11 deletions(-) (limited to 'drivers/iio/dac/ad5064.c') diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index a56b52dbefa0..3c809e2baecb 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -10,9 +10,10 @@ config AD5064 depends on (SPI_MASTER && I2C!=m) || I2C help Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, - AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668, - AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, LTC2617, LTC2619, LTC2626, - LTC2627, LTC2629 Digital to Analog Converter. + AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, AD5627, AD5627R, + AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, AD5666, + AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, + LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to Analog Converter. To compile this driver as a module, choose M here: the module will be called ad5064. diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index b7f717cadd0b..6803e4a137cd 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -1,6 +1,7 @@ /* - * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, - * AD5648, AD5666, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, + * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, + * AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, + * AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629 Digital to analog converters * driver * @@ -41,6 +42,9 @@ #define AD5064_CMD_RESET 0x7 #define AD5064_CMD_CONFIG 0x8 +#define AD5064_CMD_RESET_V2 0x5 +#define AD5064_CMD_CONFIG_V2 0x7 + #define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) #define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) @@ -51,11 +55,13 @@ /** * enum ad5064_regmap_type - Register layout variant - * @AD5064_REGMAP_ADI: Analog Devices register map layout + * @AD5064_REGMAP_ADI: Old Analog Devices register map layout + * @AD5064_REGMAP_ADI2: New Analog Devices register map layout * @AD5064_REGMAP_LTC: LTC register map layout */ enum ad5064_regmap_type { AD5064_REGMAP_ADI, + AD5064_REGMAP_ADI2, AD5064_REGMAP_LTC, }; @@ -125,14 +131,30 @@ enum ad5064_type { ID_AD5064, ID_AD5064_1, ID_AD5065, + ID_AD5625, + ID_AD5625R_1V25, + ID_AD5625R_2V5, + ID_AD5627, + ID_AD5627R_1V25, + ID_AD5627R_2V5, ID_AD5628_1, ID_AD5628_2, ID_AD5629_1, ID_AD5629_2, + ID_AD5645R_1V25, + ID_AD5645R_2V5, + ID_AD5647R_1V25, + ID_AD5647R_2V5, ID_AD5648_1, ID_AD5648_2, + ID_AD5665, + ID_AD5665R_1V25, + ID_AD5665R_2V5, ID_AD5666_1, ID_AD5666_2, + ID_AD5667, + ID_AD5667R_1V25, + ID_AD5667R_2V5, ID_AD5668_1, ID_AD5668_2, ID_AD5669_1, @@ -160,17 +182,23 @@ static int ad5064_sync_powerdown_mode(struct ad5064_state *st, const struct iio_chan_spec *chan) { unsigned int val, address; + unsigned int shift; int ret; if (st->chip_info->regmap_type == AD5064_REGMAP_LTC) { val = 0; address = chan->address; } else { - address = 0; + if (st->chip_info->regmap_type == AD5064_REGMAP_ADI2) + shift = 4; + else + shift = 8; + val = (0x1 << chan->address); + address = 0; if (st->pwr_down[chan->channel]) - val |= st->pwr_down_mode[chan->channel] << 8; + val |= st->pwr_down_mode[chan->channel] << shift; } ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, address, val, 0); @@ -391,6 +419,7 @@ static DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6, ad5064_ext_info); static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4, ad5064_ext_info); static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4, ad5064_ext_info); +static DECLARE_AD5064_CHANNELS(ad5645_channels, 14, 2, ad5064_ext_info); static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info); static DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info); @@ -440,6 +469,46 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .num_channels = 2, .regmap_type = AD5064_REGMAP_ADI, }, + [ID_AD5625] = { + .shared_vref = true, + .channels = ad5629_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5625R_1V25] = { + .shared_vref = true, + .internal_vref = 1250000, + .channels = ad5629_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5625R_2V5] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5629_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5627] = { + .shared_vref = true, + .channels = ad5629_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5627R_1V25] = { + .shared_vref = true, + .internal_vref = 1250000, + .channels = ad5629_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5627R_2V5] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5629_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, [ID_AD5628_1] = { .shared_vref = true, .internal_vref = 2500000, @@ -468,6 +537,34 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .num_channels = 8, .regmap_type = AD5064_REGMAP_ADI, }, + [ID_AD5645R_1V25] = { + .shared_vref = true, + .internal_vref = 1250000, + .channels = ad5645_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5645R_2V5] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5645_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5647R_1V25] = { + .shared_vref = true, + .internal_vref = 1250000, + .channels = ad5645_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5647R_2V5] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5645_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, [ID_AD5648_1] = { .shared_vref = true, .internal_vref = 2500000, @@ -482,6 +579,26 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .num_channels = 8, .regmap_type = AD5064_REGMAP_ADI, }, + [ID_AD5665] = { + .shared_vref = true, + .channels = ad5669_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5665R_1V25] = { + .shared_vref = true, + .internal_vref = 1250000, + .channels = ad5669_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5665R_2V5] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5669_channels, + .num_channels = 4, + .regmap_type = AD5064_REGMAP_ADI2 + }, [ID_AD5666_1] = { .shared_vref = true, .internal_vref = 2500000, @@ -496,6 +613,26 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { .num_channels = 4, .regmap_type = AD5064_REGMAP_ADI, }, + [ID_AD5667] = { + .shared_vref = true, + .channels = ad5669_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5667R_1V25] = { + .shared_vref = true, + .internal_vref = 1250000, + .channels = ad5669_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, + [ID_AD5667R_2V5] = { + .shared_vref = true, + .internal_vref = 2500000, + .channels = ad5669_channels, + .num_channels = 2, + .regmap_type = AD5064_REGMAP_ADI2 + }, [ID_AD5668_1] = { .shared_vref = true, .internal_vref = 2500000, @@ -607,6 +744,22 @@ static const char * const ad5064_vref_name(struct ad5064_state *st, return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; } +static int ad5064_set_config(struct ad5064_state *st, unsigned int val) +{ + unsigned int cmd; + + switch (st->chip_info->regmap_type) { + case AD5064_REGMAP_ADI2: + cmd = AD5064_CMD_CONFIG_V2; + break; + default: + cmd = AD5064_CMD_CONFIG; + break; + } + + return ad5064_write(st, cmd, 0, val, 0); +} + static int ad5064_probe(struct device *dev, enum ad5064_type type, const char *name, ad5064_write_func write) { @@ -636,8 +789,7 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, if (!st->chip_info->internal_vref) return ret; st->use_internal_vref = true; - ret = ad5064_write(st, AD5064_CMD_CONFIG, 0, - AD5064_CONFIG_INT_VREF_ENABLE, 0); + ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); if (ret) { dev_err(dev, "Failed to enable internal vref: %d\n", ret); @@ -766,9 +918,19 @@ static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, unsigned int addr, unsigned int val) { struct i2c_client *i2c = to_i2c_client(st->dev); + unsigned int cmd_shift; int ret; - st->data.i2c[0] = (cmd << 4) | addr; + switch (st->chip_info->regmap_type) { + case AD5064_REGMAP_ADI2: + cmd_shift = 3; + break; + default: + cmd_shift = 4; + break; + } + + st->data.i2c[0] = (cmd << cmd_shift) | addr; put_unaligned_be16(val, &st->data.i2c[1]); ret = i2c_master_send(i2c, st->data.i2c, 3); @@ -791,9 +953,23 @@ static int ad5064_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id ad5064_i2c_ids[] = { + {"ad5625", ID_AD5625 }, + {"ad5625r-1v25", ID_AD5625R_1V25 }, + {"ad5625r-2v5", ID_AD5625R_2V5 }, + {"ad5627", ID_AD5627 }, + {"ad5627r-1v25", ID_AD5627R_1V25 }, + {"ad5627r-2v5", ID_AD5627R_2V5 }, {"ad5629-1", ID_AD5629_1}, {"ad5629-2", ID_AD5629_2}, {"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */ + {"ad5645r-1v25", ID_AD5645R_1V25 }, + {"ad5645r-2v5", ID_AD5645R_2V5 }, + {"ad5665", ID_AD5665 }, + {"ad5665r-1v25", ID_AD5665R_1V25 }, + {"ad5665r-2v5", ID_AD5665R_2V5 }, + {"ad5667", ID_AD5667 }, + {"ad5667r-1v25", ID_AD5667R_1V25 }, + {"ad5667r-2v5", ID_AD5667R_2V5 }, {"ad5669-1", ID_AD5669_1}, {"ad5669-2", ID_AD5669_2}, {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */ -- cgit v1.2.3