iio: adc: ad7768-1: convert driver to use regmap

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>
This commit is contained in:
Jonathan Santos
2025-04-11 12:56:56 -03:00
committed by Jonathan Cameron
parent e5cdb098a3
commit 3f4bc0b116
2 changed files with 110 additions and 51 deletions

View 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

View 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>
@@ -53,12 +54,15 @@
#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 const struct regmap_access_table ad7768_regmap24_rd_table = {
.yes_ranges = ad7768_regmap24_rd_ranges,
.n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_rd_ranges),
};
static const struct regmap_range ad7768_regmap24_wr_ranges[] = {
regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA),
};
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),
};
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)
{
int regval;
regval = ad7768_spi_reg_read(st, AD7768_REG_CONVERSION, 1);
if (regval < 0)
return regval;
regval &= ~AD7768_CONV_MODE_MSK;
regval |= AD7768_CONV_MODE(mode);
return ad7768_spi_reg_write(st, AD7768_REG_CONVERSION, regval);
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);