iio:dac:ad5686: Add AD5310R support
authorStefan Popa <stefan.popa@analog.com>
Thu, 6 Dec 2018 13:38:30 +0000 (15:38 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 8 Dec 2018 15:35:55 +0000 (15:35 +0000)
The AD5310R is a single channel DAC with 10-bit precision, which is
part of the same family as AD5311R, except that it uses the spi interface
instead of i2c. The device has a built-in 2.5V reference which is enabled
by default.

Another important difference is that the SPI write command operation is
16 bits long. The first four bits represent the command, while the
remaining 12 bits are for data. In the control reg, DB9 and DB10 are used
for power-down modes, while DB8 is the REF bit. In order to accommodate
this change, a new regmap type was defined and checked accordingly.

Because AD5310R does not have a readback register, the read_raw operation
will return "Operation is not supported".

Datasheet:
Link: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5310R_5311R.pdf
Signed-off-by: Stefan Popa <stefan.popa@analog.com>
Signed-off-by: Mircea Caprioru <mircea.caprioru@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/dac/ad5686-spi.c
drivers/iio/dac/ad5686.c
drivers/iio/dac/ad5686.h

index 1df9143f55e986af3b3549cfecd7accc455b65f8..665fa6bd9ced7476f0f58e5cc6d5ac584f8e1c1c 100644 (file)
@@ -19,6 +19,12 @@ static int ad5686_spi_write(struct ad5686_state *st,
        u8 tx_len, *buf;
 
        switch (st->chip_info->regmap_type) {
+       case AD5310_REGMAP:
+               st->data[0].d16 = cpu_to_be16(AD5310_CMD(cmd) |
+                                             val);
+               buf = &st->data[0].d8[0];
+               tx_len = 2;
+               break;
        case AD5683_REGMAP:
                st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
                                              AD5683_DATA(val));
@@ -56,10 +62,18 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
        u8 cmd = 0;
        int ret;
 
-       if (st->chip_info->regmap_type == AD5686_REGMAP)
-               cmd = AD5686_CMD_READBACK_ENABLE;
-       else if (st->chip_info->regmap_type == AD5683_REGMAP)
+       switch (st->chip_info->regmap_type) {
+       case AD5310_REGMAP:
+               return -ENOTSUPP;
+       case AD5683_REGMAP:
                cmd = AD5686_CMD_READBACK_ENABLE_V2;
+               break;
+       case AD5686_REGMAP:
+               cmd = AD5686_CMD_READBACK_ENABLE;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
                                      AD5686_ADDR(addr));
@@ -86,6 +100,7 @@ static int ad5686_spi_remove(struct spi_device *spi)
 }
 
 static const struct spi_device_id ad5686_spi_id[] = {
+       {"ad5310r", ID_AD5310R},
        {"ad5672r", ID_AD5672R},
        {"ad5676", ID_AD5676},
        {"ad5676r", ID_AD5676R},
index 0e134b13967a5b85d68e023544178cbac434e6d8..54ff76b9336632b83a83ebf6c3520a093363e572 100644 (file)
@@ -83,6 +83,10 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
                st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
 
        switch (st->chip_info->regmap_type) {
+       case AD5310_REGMAP:
+               shift = 9;
+               ref_bit_msk = AD5310_REF_BIT_MSK;
+               break;
        case AD5683_REGMAP:
                shift = 13;
                ref_bit_msk = AD5683_REF_BIT_MSK;
@@ -221,6 +225,7 @@ static struct iio_chan_spec name[] = {                              \
                AD5868_CHANNEL(7, 7, bits, _shift),             \
 }
 
+DECLARE_AD5693_CHANNELS(ad5310r_channels, 10, 2);
 DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6);
 DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
 DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
@@ -232,6 +237,12 @@ DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2);
 DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4);
 
 static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
+       [ID_AD5310R] = {
+               .channels = ad5310r_channels,
+               .int_vref_mv = 2500,
+               .num_channels = 1,
+               .regmap_type = AD5310_REGMAP,
+       },
        [ID_AD5311R] = {
                .channels = ad5311r_channels,
                .int_vref_mv = 2500,
@@ -419,6 +430,11 @@ int ad5686_probe(struct device *dev,
        indio_dev->num_channels = st->chip_info->num_channels;
 
        switch (st->chip_info->regmap_type) {
+       case AD5310_REGMAP:
+               cmd = AD5686_CMD_CONTROL_REG;
+               ref_bit_msk = AD5310_REF_BIT_MSK;
+               st->use_internal_vref = !voltage_uv;
+               break;
        case AD5683_REGMAP:
                cmd = AD5686_CMD_CONTROL_REG;
                ref_bit_msk = AD5683_REF_BIT_MSK;
index 57b3c61bfb9143e804f0f34141f313effeb02e7c..19f6917d47383fce2756946ddc011dec0cb133d5 100644 (file)
 #include <linux/mutex.h>
 #include <linux/kernel.h>
 
+#define AD5310_CMD(x)                          ((x) << 12)
+
 #define AD5683_DATA(x)                         ((x) << 4)
+
 #define AD5686_ADDR(x)                         ((x) << 16)
 #define AD5686_CMD(x)                          ((x) << 20)
 
@@ -38,6 +41,8 @@
 
 #define AD5686_CMD_CONTROL_REG                 0x4
 #define AD5686_CMD_READBACK_ENABLE_V2          0x5
+
+#define AD5310_REF_BIT_MSK                     BIT(8)
 #define AD5683_REF_BIT_MSK                     BIT(12)
 #define AD5693_REF_BIT_MSK                     BIT(12)
 
@@ -45,6 +50,7 @@
  * ad5686_supported_device_ids:
  */
 enum ad5686_supported_device_ids {
+       ID_AD5310R,
        ID_AD5311R,
        ID_AD5671R,
        ID_AD5672R,
@@ -72,6 +78,7 @@ enum ad5686_supported_device_ids {
 };
 
 enum ad5686_regmap_type {
+       AD5310_REGMAP,
        AD5683_REGMAP,
        AD5686_REGMAP,
        AD5693_REGMAP