[PATCH v2 4/6] iio: adc: ti-ads1298: prepare for more chip families

From: Stephan Costa Barros

Date: Sat Oct 24 2026 - 19:16:13 EST


The ADS1299 has the register map of the ADS129x, with other gains, data
rates, reference and ID layout. To support it in this driver, collect
what differs between families in a chip info structure, given as match
data. The private structure has carried an unused chip_info pointer
since the driver was added.

The chip info holds:
- the regmap configuration and the PGA gain table;
- the data rate rules: the base shift, whether CONFIG1 has an HR bit,
and the oversampling ratio at DR = 0;
- the internal reference, whether CONFIG3 has the VREF_4V bit, and the
reserved bits of CONFIG3 that must be written as 1;
- a callback that checks the ID register and sets the channel count and
the name, as the ID layouts differ; bit 3 alone tells them apart.

No functional change.

Signed-off-by: Stephan Costa Barros <stephanbrrs8@xxxxxxxxx>
---
drivers/iio/adc/ti-ads1298.c | 132 +++++++++++++++++++++++++----------
1 file changed, 96 insertions(+), 36 deletions(-)

diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c
index b390c13ae..5ad543bdf 100644
--- a/drivers/iio/adc/ti-ads1298.c
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -49,8 +49,6 @@
#define ADS1298_REG_CONFIG1 0x01
#define ADS1298_MASK_CONFIG1_HR BIT(7)
#define ADS1298_MASK_CONFIG1_DR GENMASK(2, 0)
-#define ADS1298_SHIFT_DR_HR 6
-#define ADS1298_SHIFT_DR_LP 7
#define ADS1298_LOWEST_DR 0x06

#define ADS1298_REG_CONFIG2 0x02
@@ -66,6 +64,7 @@
#define ADS1298_MASK_CONFIG3_PWR_REFBUF BIT(7)
#define ADS1298_MASK_CONFIG3_RESERVED BIT(6)
#define ADS1298_MASK_CONFIG3_VREF_4V BIT(5)
+#define ADS1298_VREF_4V_MV 4000

#define ADS1298_REG_LOFF 0x04
#define ADS1298_REG_CHnSET(n) (0x05 + (n))
@@ -105,6 +104,31 @@
#define ADS1298_SPI_RDATA_BUFFER_SIZE_MAX \
ADS1298_SPI_RDATA_BUFFER_SIZE(ADS1298_MAX_CHANNELS)

+/* What differs between the chip families the driver supports */
+struct ads1298_chip_info {
+ /* Checks the ID register, and sets the channel count and the name */
+ int (*parse_id)(struct iio_dev *indio_dev, unsigned int id);
+ const struct regmap_config *regmap_config;
+ /* PGA gain for each value of the GAIN field of CHnSET */
+ const u8 *gains;
+ unsigned int num_gains;
+ /*
+ * The data rate is f_CLK >> (dr_shift + DR). With an HR bit in
+ * CONFIG1, dr_shift is that of the high-resolution mode, and the
+ * low-power mode shifts one more.
+ */
+ unsigned int dr_shift;
+ bool has_hr;
+ /* Oversampling ratio at DR = 0 */
+ unsigned int osr_base;
+ /* Internal reference, in millivolts */
+ unsigned int vref_mv;
+ /* CONFIG3 has the VREF_4V bit, which selects a 4 V internal reference */
+ bool has_vref_4v;
+ /* Reserved bits of CONFIG3 that must be written as 1 */
+ unsigned int config3_reserved;
+};
+
struct ads1298_private {
const struct ads1298_chip_info *chip_info;
struct spi_device *spi;
@@ -286,6 +310,7 @@ static int ads1298_read_one(struct ads1298_private *priv, int chan_index)

static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val)
{
+ const struct ads1298_chip_info *info = priv->chip_info;
unsigned long rate;
unsigned int cfg;
int ret;
@@ -302,10 +327,10 @@ static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val)
return -EINVAL;

/* Data rate shift depends on HR/LP mode */
- if (cfg & ADS1298_MASK_CONFIG1_HR)
- rate >>= ADS1298_SHIFT_DR_HR;
+ if (info->has_hr && !(cfg & ADS1298_MASK_CONFIG1_HR))
+ rate >>= info->dr_shift + 1;
else
- rate >>= ADS1298_SHIFT_DR_LP;
+ rate >>= info->dr_shift;

*val = rate >> (cfg & ADS1298_MASK_CONFIG1_DR);

@@ -314,6 +339,7 @@ static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val)

static int ads1298_set_samp_freq(struct ads1298_private *priv, int val)
{
+ const struct ads1298_chip_info *info = priv->chip_info;
unsigned long rate;
unsigned int factor;
unsigned int cfg;
@@ -327,9 +353,9 @@ static int ads1298_set_samp_freq(struct ads1298_private *priv, int val)
if (val <= 0)
return -EINVAL;

- factor = (rate >> ADS1298_SHIFT_DR_HR) / val;
- if (factor >= BIT(ADS1298_SHIFT_DR_LP))
- cfg = ADS1298_LOWEST_DR;
+ factor = (rate >> info->dr_shift) / val;
+ if (factor >= BIT(ADS1298_LOWEST_DR + 1))
+ cfg = ADS1298_LOWEST_DR; /* Lowest rate, in LP mode */
else if (factor)
cfg = ADS1298_MASK_CONFIG1_HR | ilog2(factor); /* Use HR mode */
else
@@ -340,11 +366,10 @@ static int ads1298_set_samp_freq(struct ads1298_private *priv, int val)
cfg);
}

-static const u8 ads1298_pga_settings[] = { 6, 1, 2, 3, 4, 8, 12 };
-
static int ads1298_get_scale(struct ads1298_private *priv,
int channel, int *val, int *val2)
{
+ const struct ads1298_chip_info *info = priv->chip_info;
unsigned int pga_idx;
int ret;
unsigned int regval;
@@ -356,13 +381,16 @@ static int ads1298_get_scale(struct ads1298_private *priv,
return ret;

*val = ret / MILLI; /* Convert to millivolts */
- } else {
+ } else if (info->has_vref_4v) {
ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG3, &regval);
if (ret)
return ret;

/* Reference in millivolts */
- *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400;
+ *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ?
+ ADS1298_VREF_4V_MV : info->vref_mv;
+ } else {
+ *val = info->vref_mv;
}

ret = regmap_read(priv->regmap, ADS1298_REG_CHnSET(channel), &regval);
@@ -370,10 +398,10 @@ static int ads1298_get_scale(struct ads1298_private *priv,
return ret;

pga_idx = FIELD_GET(ADS1298_MASK_CH_PGA, regval);
- if (pga_idx >= ARRAY_SIZE(ads1298_pga_settings))
+ if (pga_idx >= info->num_gains)
return -EINVAL;

- gain = ads1298_pga_settings[pga_idx];
+ gain = info->gains[pga_idx];
/* Full scale is VREF / gain, signed, hence the -1 */
*val2 = gain << (ADS1298_BITS_PER_SAMPLE - 1);

@@ -414,7 +442,7 @@ static int ads1298_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;

- *val = 16 << (*val & ADS1298_MASK_CONFIG1_DR);
+ *val = priv->chip_info->osr_base << (*val & ADS1298_MASK_CONFIG1_DR);
return IIO_VAL_INT;
default:
return -EINVAL;
@@ -713,31 +741,20 @@ static const struct regmap_config ads1298_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};

-static int ads1298_init(struct iio_dev *indio_dev)
+static int ads1298_parse_id(struct iio_dev *indio_dev, unsigned int id)
{
struct ads1298_private *priv = iio_priv(indio_dev);
struct device *dev = &priv->spi->dev;
const char *suffix;
unsigned int nu_ch;
- unsigned int val;
- int ret;
-
- /* Device initializes into RDATAC mode, which we don't want */
- ret = ads1298_write_cmd(priv, ADS1298_CMD_SDATAC);
- if (ret)
- return ret;
-
- ret = regmap_read(priv->regmap, ADS1298_REG_ID, &val);
- if (ret)
- return ret;

/* Fill in name and channel count based on what the chip told us */
- nu_ch = FIELD_GET(ADS1298_MASK_ID_CHANNELS, val);
+ nu_ch = FIELD_GET(ADS1298_MASK_ID_CHANNELS, id);
/* 0, 1 and 2 are 4, 6 and 8 channels; the other codes are reserved */
if (nu_ch > 2)
- return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", val);
+ return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", id);
indio_dev->num_channels = 4 + 2 * nu_ch;
- switch (val & ADS1298_MASK_ID_FAMILY) {
+ switch (id & ADS1298_MASK_ID_FAMILY) {
case ADS1298_ID_FAMILY_ADS129X:
suffix = "";
break;
@@ -745,19 +762,57 @@ static int ads1298_init(struct iio_dev *indio_dev)
suffix = "r";
break;
default:
- return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", val);
+ return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", id);
}
indio_dev->name = devm_kasprintf(dev, GFP_KERNEL, "ads129%u%s",
indio_dev->num_channels, suffix);
if (!indio_dev->name)
return -ENOMEM;

- val = ADS1298_MASK_CONFIG3_RESERVED; /* Must write 1 always */
+ return 0;
+}
+
+static const u8 ads1298_gains[] = { 6, 1, 2, 3, 4, 8, 12 };
+
+static const struct ads1298_chip_info ads1298_chip_info = {
+ .parse_id = ads1298_parse_id,
+ .regmap_config = &ads1298_regmap_config,
+ .gains = ads1298_gains,
+ .num_gains = ARRAY_SIZE(ads1298_gains),
+ .dr_shift = 6,
+ .has_hr = true,
+ .osr_base = 16,
+ .vref_mv = 2400,
+ .has_vref_4v = true,
+ .config3_reserved = ADS1298_MASK_CONFIG3_RESERVED,
+};
+
+static int ads1298_init(struct iio_dev *indio_dev)
+{
+ struct ads1298_private *priv = iio_priv(indio_dev);
+ unsigned int val;
+ int ret;
+
+ /* Device initializes into RDATAC mode, which we don't want */
+ ret = ads1298_write_cmd(priv, ADS1298_CMD_SDATAC);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(priv->regmap, ADS1298_REG_ID, &val);
+ if (ret)
+ return ret;
+
+ ret = priv->chip_info->parse_id(indio_dev, val);
+ if (ret)
+ return ret;
+
+ val = priv->chip_info->config3_reserved; /* Must write 1 always */
if (!priv->reg_vref) {
/* Enable internal reference */
val |= ADS1298_MASK_CONFIG3_PWR_REFBUF;
/* Use 4V VREF when power supply is at least 4.4V */
- if (regulator_get_voltage(priv->reg_avdd) >= 4400000)
+ if (priv->chip_info->has_vref_4v &&
+ regulator_get_voltage(priv->reg_avdd) >= 4400000)
val |= ADS1298_MASK_CONFIG3_VREF_4V;
}
ret = regmap_write(priv->regmap, ADS1298_REG_CONFIG3, val);
@@ -785,6 +840,10 @@ static int ads1298_probe(struct spi_device *spi)

priv = iio_priv(indio_dev);

+ priv->chip_info = spi_get_device_match_data(spi);
+ if (!priv->chip_info)
+ return -ENODEV;
+
/* Reset to be asserted before enabling clock and power */
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(reset_gpio))
@@ -836,7 +895,8 @@ static int ads1298_probe(struct spi_device *spi)
init_completion(&priv->completion);
init_waitqueue_head(&priv->idle_wq);
spin_lock_init(&priv->irq_busy_lock);
- priv->regmap = devm_regmap_init(dev, NULL, priv, &ads1298_regmap_config);
+ priv->regmap = devm_regmap_init(dev, NULL, priv,
+ priv->chip_info->regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);

@@ -896,13 +956,13 @@ static int ads1298_probe(struct spi_device *spi)
}

static const struct spi_device_id ads1298_id[] = {
- { .name = "ads1298" },
+ { .name = "ads1298", .driver_data = (kernel_ulong_t)&ads1298_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ads1298_id);

static const struct of_device_id ads1298_of_table[] = {
- { .compatible = "ti,ads1298" },
+ { .compatible = "ti,ads1298", .data = &ads1298_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ads1298_of_table);
--
2.43.0