@@ -322,6 +322,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 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);