[PATCH v2 4/5] iio: dac: ad5504: fix scale via output-range-microvolt

From: Taha Ed-Dafili

Date: Tue Mar 10 2026 - 13:49:35 EST


The AD5504 full-scale range is hardware-determined by the
R_SEL pin (0-30V or 0-60V). Previously, the driver incorrectly used the
VCC regulator voltage to calculate the scale.

Update the probe function to read the standard "output-range-microvolt"
property as a two-element array to determine the correct full-scale range.
Use the MILLI macro for clearer millivolt assignments and simplify the
probe logic using a local device pointer.

Suggested-by: David Lechner <dlechner@xxxxxxxxxxxx>
Suggested-by: Andy Shevchenko <andy@xxxxxxxxxx>
Signed-off-by: Taha Ed-Dafili <0rayn.dev@xxxxxxxxx>
---
drivers/iio/dac/ad5504.c | 43 ++++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e71218c44982..cd563460fc0a 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -12,10 +12,12 @@
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/types.h>
+#include <linux/units.h>

#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -271,28 +273,31 @@ static const struct iio_chan_spec ad5504_channels[] = {

static int ad5504_probe(struct spi_device *spi)
{
- const struct ad5504_platform_data *pdata = dev_get_platdata(&spi->dev);
+ struct device *dev = &spi->dev;
+ const struct ad5504_platform_data *pdata = dev_get_platdata(dev);
struct iio_dev *indio_dev;
struct ad5504_state *st;
int ret;
+ u32 range[2];

- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;

st = iio_priv(indio_dev);

- ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
- if (ret < 0 && ret != -ENODEV)
+ ret = devm_regulator_get_enable(dev, "vcc");
+ if (ret)
return ret;
- if (ret == -ENODEV) {
- if (pdata->vref_mv)
- st->vref_mv = pdata->vref_mv;
- else
- dev_warn(&spi->dev, "reference voltage unspecified\n");
- } else {
- st->vref_mv = ret / 1000;
- }
+
+ st->vref_mv = 60 * MILLI;
+ ret = device_property_read_u32_array(dev, "output-range-microvolt",
+ range, 2);
+ if (!ret && range[1] == 30 * MICRO)
+ st->vref_mv = 30 * MILLI;
+
+ if (pdata && pdata->vref_mv)
+ st->vref_mv = pdata->vref_mv;

st->spi = spi;
indio_dev->name = spi_get_device_id(st->spi)->name;
@@ -305,17 +310,17 @@ static int ad5504_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;

if (spi->irq) {
- ret = devm_request_threaded_irq(&spi->dev, spi->irq,
- NULL,
- &ad5504_event_handler,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- spi_get_device_id(st->spi)->name,
- indio_dev);
+ ret = devm_request_threaded_irq(dev, spi->irq,
+ NULL,
+ &ad5504_event_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ spi_get_device_id(st->spi)->name,
+ indio_dev);
if (ret)
return ret;
}

- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}

static const struct spi_device_id ad5504_id[] = {
--
2.47.3