[PATCH 15/22] iio: dac: ad5686: create bus ops struct

Rodrigo Alencar via B4 Relay
2026-04-22T14:46:24Z

From: Rodrigo Alencar <rodrigo.alencar@analog.com>

Create struct with bus operations, including a sync() operation that will
be used to flush multiple channel writes at once. Auxiliary functions
ad5686_write() and ad5686_read() are created and ad5686_probe() now
receives an ops struct pointer rather than individual read and write
functions. Documentation header of ad5686_state struct is updated
accordingly (adjusting renamed fields and formatting).

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
---
drivers/iio/dac/ad5686-spi.c | 7 ++++++-
drivers/iio/dac/ad5686.c | 32 ++++++++++++++------------------
drivers/iio/dac/ad5686.h | 44 ++++++++++++++++++++++++++++++++------------
drivers/iio/dac/ad5696-i2c.c | 7 ++++++-
4 files changed, 58 insertions(+), 32 deletions(-)

diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
index 6c9b70880da9..9c00e016e67c 100644
--- a/drivers/iio/dac/ad5686-spi.c
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -91,10 +91,15 @@ static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
return be32_to_cpu(st->data[2].d32);
}

+static const struct ad5686_bus_ops ad5686_spi_ops = {
+ .write = ad5686_spi_write,
+ .read = ad5686_spi_read,
+};
+
static int ad5686_spi_probe(struct spi_device *spi)
{
return ad5686_probe(&spi->dev, spi_get_device_match_data(spi),
- spi->modalias, ad5686_spi_write, ad5686_spi_read);
+ spi->modalias, &ad5686_spi_ops);
}

static const struct spi_device_id ad5686_spi_id[] = {
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 4989404a7b6e..fddcc77ab794 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -27,18 +27,18 @@ static int ad5310_control_sync(struct ad5686_state *st)
{
unsigned int pd_val = st->pwr_down_mask & st->pwr_down_mode;

- return st->write(st, AD5686_CMD_CONTROL_REG, 0,
- FIELD_PREP(AD5310_PD_MSK, pd_val) |
- FIELD_PREP(AD5310_REF_BIT_MSK, !st->use_internal_vref));
+ return ad5686_write(st, AD5686_CMD_CONTROL_REG, 0,
+ FIELD_PREP(AD5310_PD_MSK, pd_val) |
+ FIELD_PREP(AD5310_REF_BIT_MSK, !st->use_internal_vref));
}

static int ad5683_control_sync(struct ad5686_state *st)
{
unsigned int pd_val = st->pwr_down_mask & st->pwr_down_mode;

- return st->write(st, AD5686_CMD_CONTROL_REG, 0,
- FIELD_PREP(AD5683_PD_MSK, pd_val) |
- FIELD_PREP(AD5683_REF_BIT_MSK, !st->use_internal_vref));
+ return ad5686_write(st, AD5686_CMD_CONTROL_REG, 0,
+ FIELD_PREP(AD5683_PD_MSK, pd_val) |
+ FIELD_PREP(AD5683_REF_BIT_MSK, !st->use_internal_vref));
}

static inline int ad5686_pd_mask_shift(const struct iio_chan_spec *chan)
@@ -137,7 +137,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
} else {
val = lower_16_bits(val);
}
- ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, address, val);
+ ret = ad5686_write(st, AD5686_CMD_POWERDOWN_DAC, address, val);
break;
default:
ret = -EINVAL;
@@ -160,7 +160,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&st->lock);
- ret = st->read(st, chan->address);
+ ret = ad5686_read(st, chan->address);
mutex_unlock(&st->lock);
if (ret < 0)
return ret;
@@ -190,10 +190,8 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
return -EINVAL;

mutex_lock(&st->lock);
- ret = st->write(st,
- AD5686_CMD_WRITE_INPUT_N_UPDATE_N,
- chan->address,
- val << chan->scan_type.shift);
+ ret = ad5686_write(st, AD5686_CMD_WRITE_INPUT_N_UPDATE_N,
+ chan->address, val << chan->scan_type.shift);
mutex_unlock(&st->lock);
break;
default:
@@ -454,8 +452,7 @@ EXPORT_SYMBOL_NS_GPL(ad5679r_chip_info, "IIO_AD5686");

int ad5686_probe(struct device *dev,
const struct ad5686_chip_info *chip_info,
- const char *name, ad5686_write_func write,
- ad5686_read_func read)
+ const char *name, const struct ad5686_bus_ops *ops)
{
struct iio_dev *indio_dev;
struct ad5686_state *st;
@@ -468,8 +465,7 @@ int ad5686_probe(struct device *dev,
st = iio_priv(indio_dev);

st->dev = dev;
- st->write = write;
- st->read = read;
+ st->ops = ops;
st->chip_info = chip_info;

ret = devm_regulator_get_enable_optional(dev, "vdd");
@@ -525,8 +521,8 @@ int ad5686_probe(struct device *dev,
return ret;
break;
case AD5686_REGMAP:
- ret = st->write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
- !st->use_internal_vref);
+ ret = ad5686_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
+ !st->use_internal_vref);
if (ret)
return ret;
break;
diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h
index 7004d0d1d97a..55f49dbbbd39 100644
--- a/drivers/iio/dac/ad5686.h
+++ b/drivers/iio/dac/ad5686.h
@@ -56,10 +56,17 @@ enum ad5686_regmap_type {

struct ad5686_state;

-typedef int (*ad5686_write_func)(struct ad5686_state *st,
- u8 cmd, u8 addr, u16 val);
-
-typedef int (*ad5686_read_func)(struct ad5686_state *st, u8 addr);
+/**
+ * ad5686_bus_ops - bus specific read/write operations
+ * @read: read a register value at the given address
+ * @write: write a command, address and value to the device
+ * @sync: ensure the completion of the write operation (optional)
+ */
+struct ad5686_bus_ops {
+ int (*read)(struct ad5686_state *st, u8 addr);
+ int (*write)(struct ad5686_state *st, u8 cmd, u8 addr, u16 val);
+ int (*sync)(struct ad5686_state *st);
+};

/**
* struct ad5686_chip_info - chip specific information
@@ -106,24 +113,23 @@ extern const struct ad5686_chip_info ad5679r_chip_info;

/**
* struct ad5686_state - driver instance specific data
- * @spi: spi_device
+ * @dev: device instance
* @chip_info: chip model specific constants, available modes etc
+ * @ops: bus specific operations
* @vref_mv: actual reference voltage used
* @pwr_down_mask: power down mask
* @pwr_down_mode: current power down mode
* @use_internal_vref: set to true if the internal reference voltage is used
- * @lock lock to protect the data buffer during regmap ops
- * @data: spi transfer buffers
+ * @lock: lock to protect the data buffer during regmap ops
+ * @data: transfer buffers
*/
-
struct ad5686_state {
struct device *dev;
const struct ad5686_chip_info *chip_info;
+ const struct ad5686_bus_ops *ops;
unsigned short vref_mv;
unsigned int pwr_down_mask;
unsigned int pwr_down_mode;
- ad5686_write_func write;
- ad5686_read_func read;
bool use_internal_vref;
struct mutex lock;

@@ -142,8 +148,22 @@ struct ad5686_state {

int ad5686_probe(struct device *dev,
const struct ad5686_chip_info *chip_info,
- const char *name, ad5686_write_func write,
- ad5686_read_func read);
+ const char *name, const struct ad5686_bus_ops *ops);

+static inline int ad5686_write(struct ad5686_state *st, u8 cmd, u8 addr, u16 val)
+{
+ int ret;
+
+ ret = st->ops->write(st, cmd, addr, val);
+ if (ret)
+ return ret;
+
+ return st->ops->sync ? st->ops->sync(st) : 0;
+}
+
+static inline int ad5686_read(struct ad5686_state *st, u8 addr)
+{
+ return st->ops->read(st, addr);
+}

#endif /* __DRIVERS_IIO_DAC_AD5686_H__ */
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index 237f4b5df021..51cd765d80f3 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -61,10 +61,15 @@ static int ad5686_i2c_write(struct ad5686_state *st,
return (ret != 3) ? -EIO : 0;
}

+static const struct ad5686_bus_ops ad5686_i2c_ops = {
+ .write = ad5686_i2c_write,
+ .read = ad5686_i2c_read,
+};
+
static int ad5686_i2c_probe(struct i2c_client *i2c)
{
return ad5686_probe(&i2c->dev, i2c_get_match_data(i2c),
- i2c->name, ad5686_i2c_write, ad5686_i2c_read);
+ i2c->name, &ad5686_i2c_ops);
}

static const struct i2c_device_id ad5686_i2c_id[] = {

--
2.43.0