[PATCH v4 10/13] iio: dac: ds4424: support per-variant output range limits
From: Oleksij Rempel <o.rempel@pengutronix.de>
Date: 2026-02-03 09:34:37
Also in:
linux-iio, lkml
Subsystem:
iio subsystem and drivers, the rest · Maintainers:
Jonathan Cameron, Linus Torvalds
The DS4402/DS4404 variants operate with a 5-bit resolution (31 steps), whereas the DS4422/DS4424 support 7-bit (127 steps). Previously, the driver enforced a hardcoded 7-bit mask (DS4424_DAC_MASK) for all variants. This allowed users to write values exceeding the 5-bit range to DS4402/DS4404 devices, resulting in silent truncation or undefined behavior. Add a `result_mask` field to the chip_info structure to define the valid data range for each variant. Use this mask to: 1. Correctly mask register values in read_raw(). 2. Return -EINVAL in write_raw() if the input value exceeds the variant's capabilities. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> --- changes v4: - New patch - Split from the original patch (v3) to isolate 5-bit vs 7-bit handling. --- drivers/iio/dac/ds4424.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c
index 31dcf6632b58..43a622575cb5 100644
--- a/drivers/iio/dac/ds4424.c
+++ b/drivers/iio/dac/ds4424.c@@ -22,6 +22,7 @@ #define DS4424_MAX_DAC_CHANNELS 4 #define DS4424_DAC_MASK GENMASK(6, 0) +#define DS4404_DAC_MASK GENMASK(4, 0) #define DS4424_DAC_SOURCE BIT(7) #define DS4424_DAC_ADDR(chan) ((chan) + 0xf8)
@@ -35,22 +36,27 @@ } struct ds4424_chip_info { + u8 result_mask; u8 num_channels; }; static const struct ds4424_chip_info ds4402_info = { + .result_mask = DS4404_DAC_MASK, .num_channels = DS4422_MAX_DAC_CHANNELS, }; static const struct ds4424_chip_info ds4404_info = { + .result_mask = DS4404_DAC_MASK, .num_channels = DS4424_MAX_DAC_CHANNELS, }; static const struct ds4424_chip_info ds4422_info = { + .result_mask = DS4424_DAC_MASK, .num_channels = DS4422_MAX_DAC_CHANNELS, }; static const struct ds4424_chip_info ds4424_info = { + .result_mask = DS4424_DAC_MASK, .num_channels = DS4424_MAX_DAC_CHANNELS, };
@@ -60,6 +66,7 @@ struct ds4424_data { uint8_t save[DS4424_MAX_DAC_CHANNELS]; struct regulator *vcc_reg; uint8_t raw[DS4424_MAX_DAC_CHANNELS]; + const struct ds4424_chip_info *chip_info; }; static const struct iio_chan_spec ds4424_channels[] = {
@@ -110,6 +117,7 @@ static int ds4424_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { + struct ds4424_data *data = iio_priv(indio_dev); int ret, regval; switch (mask) {
@@ -122,7 +130,7 @@ static int ds4424_read_raw(struct iio_dev *indio_dev, return ret; } - *val = regval & DS4424_DAC_MASK; + *val = regval & data->chip_info->result_mask; if (!(regval & DS4424_DAC_SOURCE)) *val = -*val;
@@ -137,6 +145,7 @@ static int ds4424_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { + struct ds4424_data *data = iio_priv(indio_dev); unsigned int abs_val; if (val2 != 0)
@@ -145,7 +154,7 @@ static int ds4424_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: abs_val = abs(val); - if (abs_val > DS4424_DAC_MASK) + if (abs_val > data->chip_info->result_mask) return -EINVAL; /*
@@ -235,6 +244,7 @@ static int ds4424_probe(struct i2c_client *client) data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + data->chip_info = chip_info; data->vcc_reg = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(data->vcc_reg))
--
2.47.3