mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 22:08:33 -04:00
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:
committed by
Jonathan Cameron
parent
e5cdb098a3
commit
3f4bc0b116
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user