iio: adc: ad7768-1: convert driver to use regmap
authorJonathan Santos <Jonathan.Santos@analog.com>
Fri, 11 Apr 2025 15:56:56 +0000 (12:56 -0300)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Tue, 22 Apr 2025 18:10:04 +0000 (19:10 +0100)
Convert the AD7768-1 driver to use the regmap API for register
access. This change simplifies and standardizes register interactions,
reducing code duplication and improving maintainability.

Create two regmap configurations, one for 8-bit register values and
other for 24-bit register values.

Since we are using regmap now, define the remaining registers from 0x32
to 0x34.

Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
Link: https://patch.msgid.link/aec9e5452c1ac16d5379a80dfce97c00d85614a2.1744325346.git.Jonathan.Santos@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/Kconfig
drivers/iio/adc/ad7768-1.c

index b8e097f21a5975394e06be9e92931b298be711c6..ad06cf5567851ee71f1211ec69d59fd5c1857ee5 100644 (file)
@@ -329,6 +329,7 @@ config AD7766
 config AD7768_1
        tristate "Analog Devices AD7768-1 ADC driver"
        depends on SPI
+       select REGMAP_SPI
        select IIO_BUFFER
        select IIO_TRIGGER
        select IIO_TRIGGERED_BUFFER
index 5a863005aca6d1082b91a52655eaaa83c6871151..017d24d0bcd8525b9d22bf64e16c33c1eb08178c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/sysfs.h>
 #include <linux/spi/spi.h>
 #define AD7768_REG_SPI_DIAG_ENABLE     0x28
 #define AD7768_REG_ADC_DIAG_ENABLE     0x29
 #define AD7768_REG_DIG_DIAG_ENABLE     0x2A
-#define AD7768_REG_ADC_DATA            0x2C
+#define AD7768_REG24_ADC_DATA          0x2C
 #define AD7768_REG_MASTER_STATUS       0x2D
 #define AD7768_REG_SPI_DIAG_STATUS     0x2E
 #define AD7768_REG_ADC_DIAG_STATUS     0x2F
 #define AD7768_REG_DIG_DIAG_STATUS     0x30
 #define AD7768_REG_MCLK_COUNTER                0x31
+#define AD7768_REG_COEFF_CONTROL       0x32
+#define AD7768_REG24_COEFF_DATA                0x33
+#define AD7768_REG_ACCESS_KEY          0x34
 
 /* AD7768_REG_POWER_CLOCK */
 #define AD7768_PWR_MCLK_DIV_MSK                GENMASK(5, 4)
@@ -76,9 +80,6 @@
 #define AD7768_CONV_MODE_MSK           GENMASK(2, 0)
 #define AD7768_CONV_MODE(x)            FIELD_PREP(AD7768_CONV_MODE_MSK, x)
 
-#define AD7768_RD_FLAG_MSK(x)          (BIT(6) | ((x) & 0x3F))
-#define AD7768_WR_FLAG_MSK(x)          ((x) & 0x3F)
-
 enum ad7768_conv_mode {
        AD7768_CONTINUOUS,
        AD7768_ONE_SHOT,
@@ -153,6 +154,8 @@ static const struct iio_chan_spec ad7768_channels[] = {
 
 struct ad7768_state {
        struct spi_device *spi;
+       struct regmap *regmap;
+       struct regmap *regmap24;
        struct regulator *vref;
        struct clk *mclk;
        unsigned int mclk_freq;
@@ -175,46 +178,82 @@ struct ad7768_state {
        } data __aligned(IIO_DMA_MINALIGN);
 };
 
-static int ad7768_spi_reg_read(struct ad7768_state *st, unsigned int addr,
-                              unsigned int len)
-{
-       unsigned int shift;
-       int ret;
+static const struct regmap_range ad7768_regmap_rd_ranges[] = {
+       regmap_reg_range(AD7768_REG_CHIP_TYPE, AD7768_REG_CHIP_GRADE),
+       regmap_reg_range(AD7768_REG_SCRATCH_PAD, AD7768_REG_SCRATCH_PAD),
+       regmap_reg_range(AD7768_REG_VENDOR_L, AD7768_REG_VENDOR_H),
+       regmap_reg_range(AD7768_REG_INTERFACE_FORMAT, AD7768_REG_GAIN_LO),
+       regmap_reg_range(AD7768_REG_SPI_DIAG_ENABLE, AD7768_REG_DIG_DIAG_ENABLE),
+       regmap_reg_range(AD7768_REG_MASTER_STATUS, AD7768_REG_COEFF_CONTROL),
+       regmap_reg_range(AD7768_REG_ACCESS_KEY, AD7768_REG_ACCESS_KEY),
+};
 
-       shift = 32 - (8 * len);
-       st->data.d8[0] = AD7768_RD_FLAG_MSK(addr);
+static const struct regmap_access_table ad7768_regmap_rd_table = {
+       .yes_ranges = ad7768_regmap_rd_ranges,
+       .n_yes_ranges = ARRAY_SIZE(ad7768_regmap_rd_ranges),
+};
 
-       ret = spi_write_then_read(st->spi, st->data.d8, 1,
-                                 &st->data.d32, len);
-       if (ret < 0)
-               return ret;
+static const struct regmap_range ad7768_regmap_wr_ranges[] = {
+       regmap_reg_range(AD7768_REG_SCRATCH_PAD, AD7768_REG_SCRATCH_PAD),
+       regmap_reg_range(AD7768_REG_INTERFACE_FORMAT, AD7768_REG_GPIO_WRITE),
+       regmap_reg_range(AD7768_REG_OFFSET_HI, AD7768_REG_GAIN_LO),
+       regmap_reg_range(AD7768_REG_SPI_DIAG_ENABLE, AD7768_REG_DIG_DIAG_ENABLE),
+       regmap_reg_range(AD7768_REG_SPI_DIAG_STATUS, AD7768_REG_SPI_DIAG_STATUS),
+       regmap_reg_range(AD7768_REG_COEFF_CONTROL, AD7768_REG_COEFF_CONTROL),
+       regmap_reg_range(AD7768_REG_ACCESS_KEY, AD7768_REG_ACCESS_KEY),
+};
 
-       return (be32_to_cpu(st->data.d32) >> shift);
-}
+static const struct regmap_access_table ad7768_regmap_wr_table = {
+       .yes_ranges = ad7768_regmap_wr_ranges,
+       .n_yes_ranges = ARRAY_SIZE(ad7768_regmap_wr_ranges),
+};
 
-static int ad7768_spi_reg_write(struct ad7768_state *st,
-                               unsigned int addr,
-                               unsigned int val)
-{
-       st->data.d8[0] = AD7768_WR_FLAG_MSK(addr);
-       st->data.d8[1] = val & 0xFF;
+static const struct regmap_config ad7768_regmap_config = {
+       .name = "ad7768-1-8",
+       .reg_bits = 8,
+       .val_bits = 8,
+       .read_flag_mask = BIT(6),
+       .rd_table = &ad7768_regmap_rd_table,
+       .wr_table = &ad7768_regmap_wr_table,
+       .max_register = AD7768_REG_ACCESS_KEY,
+       .use_single_write = true,
+       .use_single_read = true,
+};
 
-       return spi_write(st->spi, st->data.d8, 2);
-}
+static const struct regmap_range ad7768_regmap24_rd_ranges[] = {
+       regmap_reg_range(AD7768_REG24_ADC_DATA, AD7768_REG24_ADC_DATA),
+       regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA),
+};
 
-static int ad7768_set_mode(struct ad7768_state *st,
-                          enum ad7768_conv_mode mode)
-{
-       int regval;
+static const struct regmap_access_table ad7768_regmap24_rd_table = {
+       .yes_ranges = ad7768_regmap24_rd_ranges,
+       .n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_rd_ranges),
+};
 
-       regval = ad7768_spi_reg_read(st, AD7768_REG_CONVERSION, 1);
-       if (regval < 0)
-               return regval;
+static const struct regmap_range ad7768_regmap24_wr_ranges[] = {
+       regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA),
+};
 
-       regval &= ~AD7768_CONV_MODE_MSK;
-       regval |= AD7768_CONV_MODE(mode);
+static const struct regmap_access_table ad7768_regmap24_wr_table = {
+       .yes_ranges = ad7768_regmap24_wr_ranges,
+       .n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_wr_ranges),
+};
 
-       return ad7768_spi_reg_write(st, AD7768_REG_CONVERSION, regval);
+static const struct regmap_config ad7768_regmap24_config = {
+       .name = "ad7768-1-24",
+       .reg_bits = 8,
+       .val_bits = 24,
+       .read_flag_mask = BIT(6),
+       .rd_table = &ad7768_regmap24_rd_table,
+       .wr_table = &ad7768_regmap24_wr_table,
+       .max_register = AD7768_REG24_COEFF_DATA,
+};
+
+static int ad7768_set_mode(struct ad7768_state *st,
+                          enum ad7768_conv_mode mode)
+{
+       return regmap_update_bits(st->regmap, AD7768_REG_CONVERSION,
+                                AD7768_CONV_MODE_MSK, AD7768_CONV_MODE(mode));
 }
 
 static int ad7768_scan_direct(struct iio_dev *indio_dev)
@@ -233,9 +272,10 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev)
        if (!ret)
                return -ETIMEDOUT;
 
-       readval = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
-       if (readval < 0)
-               return readval;
+       ret = regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &readval);
+       if (ret)
+               return ret;
+
        /*
         * Any SPI configuration of the AD7768-1 can only be
         * performed in continuous conversion mode.
@@ -258,16 +298,23 @@ static int ad7768_reg_access(struct iio_dev *indio_dev,
        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;
 
+       ret = -EINVAL;
        if (readval) {
-               ret = ad7768_spi_reg_read(st, reg, 1);
-               if (ret < 0)
-                       goto err_release;
-               *readval = ret;
-               ret = 0;
+               if (regmap_check_range_table(st->regmap, reg, &ad7768_regmap_rd_table))
+                       ret = regmap_read(st->regmap, reg, readval);
+
+               if (regmap_check_range_table(st->regmap24, reg, &ad7768_regmap24_rd_table))
+                       ret = regmap_read(st->regmap24, reg, readval);
+
        } else {
-               ret = ad7768_spi_reg_write(st, reg, writeval);
+               if (regmap_check_range_table(st->regmap, reg, &ad7768_regmap_wr_table))
+                       ret = regmap_write(st->regmap, reg, writeval);
+
+               if (regmap_check_range_table(st->regmap24, reg, &ad7768_regmap24_wr_table))
+                       ret = regmap_write(st->regmap24, reg, writeval);
+
        }
-err_release:
+
        iio_device_release_direct(indio_dev);
 
        return ret;
@@ -284,7 +331,7 @@ static int ad7768_set_dig_fil(struct ad7768_state *st,
        else
                mode = AD7768_DIG_FIL_DEC_RATE(dec_rate);
 
-       ret = ad7768_spi_reg_write(st, AD7768_REG_DIGITAL_FILTER, mode);
+       ret = regmap_write(st->regmap, AD7768_REG_DIGITAL_FILTER, mode);
        if (ret < 0)
                return ret;
 
@@ -321,7 +368,7 @@ static int ad7768_set_freq(struct ad7768_state *st,
         */
        pwr_mode = AD7768_PWR_MCLK_DIV(ad7768_clk_config[idx].mclk_div) |
                   AD7768_PWR_PWRMODE(ad7768_clk_config[idx].pwrmode);
-       ret = ad7768_spi_reg_write(st, AD7768_REG_POWER_CLOCK, pwr_mode);
+       ret = regmap_write(st->regmap, AD7768_REG_POWER_CLOCK, pwr_mode);
        if (ret < 0)
                return ret;
 
@@ -446,11 +493,11 @@ static int ad7768_setup(struct ad7768_state *st)
         * to 10. When the sequence is detected, the reset occurs.
         * See the datasheet, page 70.
         */
-       ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x3);
+       ret = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x3);
        if (ret)
                return ret;
 
-       ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x2);
+       ret = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x2);
        if (ret)
                return ret;
 
@@ -505,18 +552,19 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev)
         * continuous read mode. Subsequent data reads do not require an
         * initial 8-bit write to query the ADC_DATA register.
         */
-       return ad7768_spi_reg_write(st, AD7768_REG_INTERFACE_FORMAT, 0x01);
+       return regmap_write(st->regmap, AD7768_REG_INTERFACE_FORMAT, 0x01);
 }
 
 static int ad7768_buffer_predisable(struct iio_dev *indio_dev)
 {
        struct ad7768_state *st = iio_priv(indio_dev);
+       unsigned int unused;
 
        /*
         * To exit continuous read mode, perform a single read of the ADC_DATA
         * reg (0x2C), which allows further configuration of the device.
         */
-       return ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
+       return regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused);
 }
 
 static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
@@ -587,6 +635,16 @@ static int ad7768_probe(struct spi_device *spi)
 
        st->spi = spi;
 
+       st->regmap = devm_regmap_init_spi(spi, &ad7768_regmap_config);
+       if (IS_ERR(st->regmap))
+               return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
+                                    "Failed to initialize regmap");
+
+       st->regmap24 = devm_regmap_init_spi(spi, &ad7768_regmap24_config);
+       if (IS_ERR(st->regmap24))
+               return dev_err_probe(&spi->dev, PTR_ERR(st->regmap24),
+                                    "Failed to initialize regmap24");
+
        st->vref = devm_regulator_get(&spi->dev, "vref");
        if (IS_ERR(st->vref))
                return PTR_ERR(st->vref);