[PATCH v2 1/4] iio: dac: ad3530r: Refactor setup to table-driven register bank approach

From: Kim Seer Paller

Date: Mon Jun 15 2026 - 02:21:17 EST


Replace direct register calls in ad3530r_setup() with per-chip register
address arrays and bank helpers (ad3530r_set_reg_bank_bits,
ad3530r_write_reg_banks). Convert sw_ldac_trig_reg from a static
register address to a function pointer for per-bank LDAC trigger
register selection. Switch spi_device_id to named initializers.

Signed-off-by: Kim Seer Paller <kimseer.paller@xxxxxxxxxx>
---
drivers/iio/dac/ad3530r.c | 144 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 118 insertions(+), 26 deletions(-)

diff --git a/drivers/iio/dac/ad3530r.c b/drivers/iio/dac/ad3530r.c
index d9db3226ecd6..e4346bc729ba 100644
--- a/drivers/iio/dac/ad3530r.c
+++ b/drivers/iio/dac/ad3530r.c
@@ -69,8 +69,14 @@ struct ad3530r_chip_info {
const char *name;
const struct iio_chan_spec *channels;
int (*input_ch_reg)(unsigned int channel);
+ int (*sw_ldac_trig_reg)(unsigned int channel);
+ const unsigned int *interface_config_a;
+ const unsigned int *output_control;
+ const unsigned int *reference_control;
+ const unsigned int *op_mode;
unsigned int num_channels;
- unsigned int sw_ldac_trig_reg;
+ unsigned int num_banks;
+ unsigned int num_op_mode_regs;
bool internal_ref_support;
};

@@ -190,6 +196,16 @@ static ssize_t ad3530r_set_dac_powerdown(struct iio_dev *indio_dev,
return len;
}

+static int ad3530r_trigger_sw_ldac_reg(unsigned int channel)
+{
+ return AD3530R_SW_LDAC_TRIG_A;
+}
+
+static int ad3531r_trigger_sw_ldac_reg(unsigned int channel)
+{
+ return AD3531R_SW_LDAC_TRIG_A;
+}
+
static int ad3530r_trigger_hw_ldac(struct gpio_desc *ldac_gpio)
{
gpiod_set_value_cansleep(ldac_gpio, 1);
@@ -215,7 +231,7 @@ static int ad3530r_dac_write(struct ad3530r_state *st, unsigned int chan,
if (st->ldac_gpio)
return ad3530r_trigger_hw_ldac(st->ldac_gpio);

- return regmap_set_bits(st->regmap, st->chip_info->sw_ldac_trig_reg,
+ return regmap_set_bits(st->regmap, st->chip_info->sw_ldac_trig_reg(chan),
AD3530R_SLD_TRIG_A);
}

@@ -331,12 +347,39 @@ static const struct iio_chan_spec ad3531r_channels[] = {
AD3530R_CHAN(3, ad3531r_ext_info),
};

+static const unsigned int ad3530r_if_config[] = {
+ AD3530R_INTERFACE_CONFIG_A,
+};
+
+static const unsigned int ad3530r_out_ctrl[] = {
+ AD3530R_OUTPUT_CONTROL_0,
+};
+
+static const unsigned int ad3530r_ref_ctrl[] = {
+ AD3530R_REFERENCE_CONTROL_0,
+};
+
+static const unsigned int ad3530r_op_mode[] = {
+ AD3530R_OUTPUT_OPERATING_MODE_0,
+ AD3530R_OUTPUT_OPERATING_MODE_1,
+};
+
+static const unsigned int ad3531r_op_mode[] = {
+ AD3530R_OUTPUT_OPERATING_MODE_0,
+};
+
static const struct ad3530r_chip_info ad3530_chip = {
.name = "ad3530",
.channels = ad3530r_channels,
.num_channels = ARRAY_SIZE(ad3530r_channels),
- .sw_ldac_trig_reg = AD3530R_SW_LDAC_TRIG_A,
+ .sw_ldac_trig_reg = ad3530r_trigger_sw_ldac_reg,
.input_ch_reg = ad3530r_input_ch_reg,
+ .interface_config_a = ad3530r_if_config,
+ .output_control = ad3530r_out_ctrl,
+ .reference_control = ad3530r_ref_ctrl,
+ .op_mode = ad3530r_op_mode,
+ .num_banks = ARRAY_SIZE(ad3530r_if_config),
+ .num_op_mode_regs = ARRAY_SIZE(ad3530r_op_mode),
.internal_ref_support = false,
};

@@ -344,7 +387,14 @@ static const struct ad3530r_chip_info ad3530r_chip = {
.name = "ad3530r",
.channels = ad3530r_channels,
.num_channels = ARRAY_SIZE(ad3530r_channels),
- .sw_ldac_trig_reg = AD3530R_SW_LDAC_TRIG_A,
+ .sw_ldac_trig_reg = ad3530r_trigger_sw_ldac_reg,
+ .input_ch_reg = ad3530r_input_ch_reg,
+ .interface_config_a = ad3530r_if_config,
+ .output_control = ad3530r_out_ctrl,
+ .reference_control = ad3530r_ref_ctrl,
+ .op_mode = ad3530r_op_mode,
+ .num_banks = ARRAY_SIZE(ad3530r_if_config),
+ .num_op_mode_regs = ARRAY_SIZE(ad3530r_op_mode),
.input_ch_reg = ad3530r_input_ch_reg,
.internal_ref_support = true,
};
@@ -353,8 +403,14 @@ static const struct ad3530r_chip_info ad3531_chip = {
.name = "ad3531",
.channels = ad3531r_channels,
.num_channels = ARRAY_SIZE(ad3531r_channels),
- .sw_ldac_trig_reg = AD3531R_SW_LDAC_TRIG_A,
+ .sw_ldac_trig_reg = ad3531r_trigger_sw_ldac_reg,
.input_ch_reg = ad3531r_input_ch_reg,
+ .interface_config_a = ad3530r_if_config,
+ .output_control = ad3530r_out_ctrl,
+ .reference_control = ad3530r_ref_ctrl,
+ .op_mode = ad3531r_op_mode,
+ .num_banks = ARRAY_SIZE(ad3530r_if_config),
+ .num_op_mode_regs = ARRAY_SIZE(ad3531r_op_mode),
.internal_ref_support = false,
};

@@ -362,17 +418,56 @@ static const struct ad3530r_chip_info ad3531r_chip = {
.name = "ad3531r",
.channels = ad3531r_channels,
.num_channels = ARRAY_SIZE(ad3531r_channels),
- .sw_ldac_trig_reg = AD3531R_SW_LDAC_TRIG_A,
+ .sw_ldac_trig_reg = ad3531r_trigger_sw_ldac_reg,
.input_ch_reg = ad3531r_input_ch_reg,
+ .interface_config_a = ad3530r_if_config,
+ .output_control = ad3530r_out_ctrl,
+ .reference_control = ad3530r_ref_ctrl,
+ .op_mode = ad3531r_op_mode,
+ .num_banks = ARRAY_SIZE(ad3530r_if_config),
+ .num_op_mode_regs = ARRAY_SIZE(ad3531r_op_mode),
.internal_ref_support = true,
};

+static int ad3530r_set_reg_bank_bits(const struct ad3530r_state *st,
+ const unsigned int *regs,
+ unsigned int num_regs,
+ unsigned int mask)
+{
+ int ret;
+
+ for (unsigned int i = 0; i < num_regs; i++) {
+ ret = regmap_update_bits(st->regmap, regs[i], mask, mask);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad3530r_write_reg_banks(const struct ad3530r_state *st,
+ const unsigned int *regs,
+ unsigned int num_regs,
+ unsigned int val)
+{
+ int ret;
+
+ for (unsigned int i = 0; i < num_regs; i++) {
+ ret = regmap_write(st->regmap, regs[i], val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int ad3530r_setup(struct ad3530r_state *st, int external_vref_uV)
{
+ const struct ad3530r_chip_info *chip_info = st->chip_info;
struct device *dev = regmap_get_device(st->regmap);
struct gpio_desc *reset_gpio;
- int i, ret;
u8 range_multiplier, val;
+ int ret;

reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(reset_gpio))
@@ -385,8 +480,9 @@ static int ad3530r_setup(struct ad3530r_state *st, int external_vref_uV)
gpiod_set_value_cansleep(reset_gpio, 0);
} else {
/* Perform software reset */
- ret = regmap_update_bits(st->regmap, AD3530R_INTERFACE_CONFIG_A,
- AD3530R_SW_RESET, AD3530R_SW_RESET);
+ ret = ad3530r_set_reg_bank_bits(st, chip_info->interface_config_a,
+ chip_info->num_banks,
+ AD3530R_SW_RESET);
if (ret)
return ret;
}
@@ -395,8 +491,9 @@ static int ad3530r_setup(struct ad3530r_state *st, int external_vref_uV)

range_multiplier = 1;
if (device_property_read_bool(dev, "adi,range-double")) {
- ret = regmap_set_bits(st->regmap, AD3530R_OUTPUT_CONTROL_0,
- AD3530R_OUTPUT_CONTROL_RANGE);
+ ret = ad3530r_set_reg_bank_bits(st, chip_info->output_control,
+ chip_info->num_banks,
+ AD3530R_OUTPUT_CONTROL_RANGE);
if (ret)
return ret;

@@ -406,8 +503,9 @@ static int ad3530r_setup(struct ad3530r_state *st, int external_vref_uV)
if (external_vref_uV) {
st->vref_mV = range_multiplier * external_vref_uV / MILLI;
} else {
- ret = regmap_set_bits(st->regmap, AD3530R_REFERENCE_CONTROL_0,
- AD3530R_REFERENCE_CONTROL_SEL);
+ ret = ad3530r_set_reg_bank_bits(st, chip_info->reference_control,
+ chip_info->num_banks,
+ AD3530R_REFERENCE_CONTROL_SEL);
if (ret)
return ret;

@@ -420,18 +518,12 @@ static int ad3530r_setup(struct ad3530r_state *st, int external_vref_uV)
FIELD_PREP(AD3530R_OP_MODE_CHAN_MSK(2), AD3530R_NORMAL_OP) |
FIELD_PREP(AD3530R_OP_MODE_CHAN_MSK(3), AD3530R_NORMAL_OP);

- ret = regmap_write(st->regmap, AD3530R_OUTPUT_OPERATING_MODE_0, val);
+ ret = ad3530r_write_reg_banks(st, st->chip_info->op_mode,
+ st->chip_info->num_op_mode_regs, val);
if (ret)
return ret;

- if (st->chip_info->num_channels > 4) {
- ret = regmap_write(st->regmap, AD3530R_OUTPUT_OPERATING_MODE_1,
- val);
- if (ret)
- return ret;
- }
-
- for (i = 0; i < st->chip_info->num_channels; i++)
+ for (unsigned int i = 0; i < st->chip_info->num_channels; i++)
st->chan[i].powerdown_mode = AD3530R_POWERDOWN_32K;

st->ldac_gpio = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_LOW);
@@ -510,10 +602,10 @@ static int ad3530r_probe(struct spi_device *spi)
}

static const struct spi_device_id ad3530r_id[] = {
- { "ad3530", (kernel_ulong_t)&ad3530_chip },
- { "ad3530r", (kernel_ulong_t)&ad3530r_chip },
- { "ad3531", (kernel_ulong_t)&ad3531_chip },
- { "ad3531r", (kernel_ulong_t)&ad3531r_chip },
+ { .name = "ad3530", .driver_data = (kernel_ulong_t)&ad3530_chip },
+ { .name = "ad3530r", .driver_data = (kernel_ulong_t)&ad3530r_chip },
+ { .name = "ad3531", .driver_data = (kernel_ulong_t)&ad3531_chip },
+ { .name = "ad3531r", .driver_data = (kernel_ulong_t)&ad3531r_chip },
{ }
};
MODULE_DEVICE_TABLE(spi, ad3530r_id);

--
2.34.1