[PATCH v2 4/7] iio: adc: ti-ads1262: Add excitation current support
From: Kurt Borja
Date: Sun Jun 28 2026 - 01:37:37 EST
Support the two IDAC excitation current sources. Each channel can route
its IDAC1/IDAC2 outputs to a pin via the "excitation-channels" property
and select a magnitude via "excitation-current-nanoamp".
Signed-off-by: Kurt Borja <kuurtb@xxxxxxxxx>
---
drivers/iio/adc/ti-ads1262.c | 78 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/ti-ads1262.c b/drivers/iio/adc/ti-ads1262.c
index ece97a0c2b1304ad..8921eaae537f6b0a 100644
--- a/drivers/iio/adc/ti-ads1262.c
+++ b/drivers/iio/adc/ti-ads1262.c
@@ -193,6 +193,22 @@ enum {
ADS1262_INPMUX_LAST
};
+enum {
+ ADS1262_IDACMUX_AIN0,
+ ADS1262_IDACMUX_AIN1,
+ ADS1262_IDACMUX_AIN2,
+ ADS1262_IDACMUX_AIN3,
+ ADS1262_IDACMUX_AIN4,
+ ADS1262_IDACMUX_AIN5,
+ ADS1262_IDACMUX_AIN6,
+ ADS1262_IDACMUX_AIN7,
+ ADS1262_IDACMUX_AIN8,
+ ADS1262_IDACMUX_AIN9,
+ ADS1262_IDACMUX_AINCOM,
+ ADS1262_IDACMUX_NO_CONN,
+ ADS1262_IDACMUX_LAST
+};
+
enum {
ADS1262_REFMUX_INTERNAL,
ADS1262_REFMUX_AIN0_AIN1,
@@ -213,6 +229,8 @@ struct ads1262_channel {
u8 gain;
u8 data_rate;
u8 reference[3];
+ u8 idac_mux[2];
+ u8 idac_mag[2];
u8 pga_bypass:1;
u8 ref_reversal:1;
u8 input_chop:1;
@@ -450,7 +468,7 @@ static int ads1262_dev_read_by_cmd(struct ads1262 *st, u8 cmd, __be32 *val)
static int ads1262_channel_enable(struct ads1262 *st,
struct ads1262_channel *chan)
{
- u8 mode0, mode1, mode2, inpmux, refmux;
+ u8 mode0, mode1, mode2, inpmux, idacmux, idacmag, refmux;
int ret;
/* Avoid using guard() here to mitigate AB/BA deadlock warning */
@@ -464,6 +482,10 @@ static int ads1262_channel_enable(struct ads1262 *st,
FIELD_PREP(ADS1262_MODE2_BYPASS_MASK, chan->pga_bypass);
inpmux = FIELD_PREP(ADS1262_INPMUX_MUXN_MASK, chan->input[1]) |
FIELD_PREP(ADS1262_INPMUX_MUXP_MASK, chan->input[0]);
+ idacmux = FIELD_PREP(ADS1262_IDACMUX_MUX1_MASK, chan->idac_mux[0]) |
+ FIELD_PREP(ADS1262_IDACMUX_MUX2_MASK, chan->idac_mux[1]);
+ idacmag = FIELD_PREP(ADS1262_IDACMAG_MAG1_MASK, chan->idac_mag[0]) |
+ FIELD_PREP(ADS1262_IDACMAG_MAG2_MASK, chan->idac_mag[1]);
refmux = FIELD_PREP(ADS1262_REFMUX_RMUXN_MASK, chan->reference[1]) |
FIELD_PREP(ADS1262_REFMUX_RMUXP_MASK, chan->reference[0]);
mutex_unlock(&st->chan_lock);
@@ -493,6 +515,18 @@ static int ads1262_channel_enable(struct ads1262 *st,
if (ret)
return ret;
+ ret = regmap_update_bits(st->regmap, ADS1262_IDACMUX_REG,
+ ADS1262_IDACMUX_MUX1_MASK |
+ ADS1262_IDACMUX_MUX2_MASK, idacmux);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, ADS1262_IDACMAG_REG,
+ ADS1262_IDACMAG_MAG1_MASK |
+ ADS1262_IDACMAG_MAG2_MASK, idacmag);
+ if (ret)
+ return ret;
+
return regmap_update_bits(st->regmap, ADS1262_REFMUX_REG,
ADS1262_REFMUX_RMUXN_MASK |
ADS1262_REFMUX_RMUXP_MASK, refmux);
@@ -1040,13 +1074,19 @@ static int ads1262_parse_channel_node(struct ads1262 *st,
struct fwnode_handle *node)
{
struct device *dev = &st->spi->dev;
+ static const u32 idac_nA[] = {
+ 0, 50000, 100000, 250000, 500000, 750000,
+ 1000000, 1500000, 2000000, 2500000, 3000000
+ };
const char *ref_sources[3] = {};
- u32 pins[2];
+ u32 pins[2], mags[2];
int ret;
/* Write non-zero default configuration values */
chan->filter = ADS1262_FILTER_FIR;
chan->data_rate = ADS1262_DR_20_SPS;
+ chan->idac_mux[0] = ADS1262_IDACMUX_NO_CONN;
+ chan->idac_mux[1] = ADS1262_IDACMUX_NO_CONN;
ret = fwnode_property_read_u32_array(node, "diff-channels", pins, ARRAY_SIZE(pins));
if (ret)
@@ -1086,6 +1126,40 @@ static int ads1262_parse_channel_node(struct ads1262 *st,
}
}
+ if (fwnode_property_present(node, "excitation-channels")) {
+ ret = fwnode_property_read_u32_array(node, "excitation-channels",
+ pins, ARRAY_SIZE(pins));
+ if (ret)
+ return dev_err_probe(dev, ret, "%s: Failed to read excitation-channels\n",
+ fwnode_get_name(node));
+ if (pins[0] >= ADS1262_IDACMUX_LAST || pins[1] >= ADS1262_IDACMUX_LAST)
+ return dev_err_probe(dev, -EINVAL, "%s: excitation-channels not in range\n",
+ fwnode_get_name(node));
+ chan->idac_mux[0] = pins[0];
+ chan->idac_mux[1] = pins[1];
+
+ ret = fwnode_property_read_u32_array(node, "excitation-current-nanoamp",
+ mags, ARRAY_SIZE(mags));
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "%s: Failed to read excitation-current-nanoamp\n",
+ fwnode_get_name(node));
+
+ ret = ads1262_find_one(idac_nA, mags[0]);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "%s: Invalid excitation-current-nanoamp\n",
+ fwnode_get_name(node));
+ chan->idac_mag[0] = ret;
+
+ ret = ads1262_find_one(idac_nA, mags[1]);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "%s: Invalid excitation-current-nanoamp\n",
+ fwnode_get_name(node));
+ chan->idac_mag[1] = ret;
+ }
+
if (fwnode_property_present(node, "ti,pga-bypass"))
chan->pga_bypass = 1;
--
2.54.0