Skip to contentSkip to conversation

iio: dac: ad5504: fix voltage scaling and add missing bindings

PATCH Superseded Taha Ed-Dafili 4 participants 11 messages Feb 12 – Feb 16

Subsystems (3)

v1 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

cover iio: dac: ad5504: fix voltage scaling and add missing bindings

This series fixes the voltage scale calculation for the AD5504 DAC and updates the devicetree bindings to support the necessary hardware configuration.

Previously, the driver calculated the scale based on the VCC supply voltage.

However, as confirmed by the datasheet (Rev. B) and discussion on the mailing list [1], the AD5504 has an integrated precision reference, and the output range is determined strictly by the state of the R_SEL pin (0-30V or 0-60V).

To address this:
1. Patch 1 adds adi,output-range-volts (and GPIO equivalents) to the bindings to describe the hardware state of the R_SEL pin, along with other missing properties (vlogic, clear, ldac).
2. Patch 2 updates the driver to use this property for scale calculation, falling back to the 60V range if unspecified, while retaining the VCC regulator enable for power.

Taha Ed-Dafili (2):
dt-bindings: iio: dac: ad5504: add output-range and missing gpios
iio: dac: ad5504: use adi,output-range-volts for scale calculation

 Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml | 20 ++++++++++++++++++++
 drivers/iio/dac/ad5504.c                                  | 15 ++++++++++-----
 2 files changed, 30 insertions(+), 5 deletions(-)

Taha Ed-Dafili (2):
dt-bindings: iio: dac: ad5504: add output-range and missing gpios
iio: dac: ad5504: use adi,output-range-volts for scale calculation

 .../bindings/iio/dac/adi,ad5504.yaml          | 38 +++++++++++++++++++
 drivers/iio/dac/ad5504.c                      | 26 ++++++++-----
 2 files changed, 54 insertions(+), 10 deletions(-)
Signature · 1 line
2.47.3
#1 lore raw

PATCH 1/2 dt-bindings: iio: dac: ad5504: add output-range and missing gpios

The AD5504 output range (0-30V or 0-60V) is determined by the R_SEL pin.

Add adi,output-range-volts and adi,output-range-gpios to describe this hardware state, using allOf to enforce mutual exclusivity. Also add vlogic-supply, clear-gpios, and ldac-gpios to complete the hardware description.

---
 .../bindings/iio/dac/adi,ad5504.yaml          | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +38 -0
index 9c2c038683b4..3e832e501b0e 100644
@@ -27,12 +27,50 @@ properties:
     maxItems: 1
 
   vcc-supply: true
+  vlogic-supply: true
+
+  adi,output-range-volts:
+    description:
+      Hard-wired /R_SEL pin state. 30 V when pin is high and 60 V when
+      pin is low.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [30, 60]
+    default: 60
+
+  adi,output-range-gpios:
+    description:
+      GPIO connected to the R_SEL pin to select the output voltage range.
+    maxItems: 1
+
+  clear-gpios:
+    description: GPIO that controls the /CLR pin (active low).
+    maxItems: 1
+
+  ldac-gpios:
+    description: GPIO that controls the /LDAC pin (active low).
+    maxItems: 1
 
 additionalProperties: false
 
 required:
   - compatible
   - reg
+  - vcc-supply
+
+allOf:
+  - if:
+      required:
+        - adi,output-range-gpios
+    then:
+      properties:
+        adi,output-range-volts: false
+
+  - if:
+      required:
+        - adi,output-range-volts
+    then:
+      properties:
+        adi,output-range-gpios: false
 
 examples:
   - |
Signature · 1 line
2.47.3
#2 lore raw

Re: [PATCH v1 1/2] dt-bindings: iio: dac: ad5504: add output-range and missing gpios

Quoted 18 lines · Taha Ed-Dafili

The AD5504 output range (0-30V or 0-60V) is determined by the R_SEL pin.

Add adi,output-range-volts and adi,output-range-gpios to describe this hardware state, using allOf to enforce mutual exclusivity. Also add vlogic-supply, clear-gpios, and ldac-gpios to complete the hardware description.

---
 .../bindings/iio/dac/adi,ad5504.yaml          | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +0 -0
index 9c2c038683b4..3e832e501b0e 100644

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml properties: · line 32

Quoted 6 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +3 -0
@@ -27,12 +27,50 @@ properties:
     maxItems: 1
 
   vcc-supply: true
+  vlogic-supply: true
+
+  adi,output-range-volts:

Use proper property unit suffix, see dt-schema.

And really, you should have checked - you already have properties for this! See dac schema.

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml properties: · line 40

Quoted 8 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +8 -0
+    description:
+      Hard-wired /R_SEL pin state. 30 V when pin is high and 60 V when
+      pin is low.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [30, 60]
+    default: 60
+
+  adi,output-range-gpios:

So another same roperty? If you looked around you would find adi,range-gpios, which would be better than multiplying properties. Anyway, gpios do not take vendor prefixes, so you want range-sel-gpios or range-gpios. I guess the latter.

Quoted 10 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +10 -0
+    description:
+      GPIO connected to the R_SEL pin to select the output voltage range.
+    maxItems: 1
+
+  clear-gpios:
+    description: GPIO that controls the /CLR pin (active low).
+    maxItems: 1
+
+  ldac-gpios:
+    description: GPIO that controls the /LDAC pin (active low).

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml properties: · line 60

Quoted 10 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +4 -0
+    maxItems: 1
 
 additionalProperties: false
 
 required:
   - compatible
   - reg
+  - vcc-supply
+
+allOf:

allOf:
- not:
required:
- foo
- bar

Should give you exactly same result, with less code.

Quoted 19 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +13 -0
+  - if:
+      required:
+        - adi,output-range-gpios
+    then:
+      properties:
+        adi,output-range-volts: false
+
+  - if:
+      required:
+        - adi,output-range-volts
+    then:
+      properties:
+        adi,output-range-gpios: false
 
 examples:
   - |
Signature · 1 line
2.47.3
#3 lore raw

Re: [PATCH v1 1/2] dt-bindings: iio: dac: ad5504: add output-range and missing gpios

Hello Krzysztof,

Thank you for the detailed review and for pointing me toward the standard DAC schema.

I'll update the bindings in v2 to address your comments, and I will also ensure I check the common schemas more thoroughly for future patches.

Best regards,
Taha

#4 lore raw

Re: [PATCH v1 1/2] dt-bindings: iio: dac: ad5504: add output-range and missing gpios

Quoted 7 lines · Taha Ed-Dafili

Hello Krzysztof,

Thank you for the detailed review and for pointing me toward the standard DAC schema.

I'll update the bindings in v2 to address your comments, and I will also ensure I check the common schemas more thoroughly for future patches.

Thanks.

Best regards,
Krzysztof

#5 lore raw

PATCH 2/2 iio: dac: ad5504: use adi,output-range-volts for scale calculation

In reply to Taha Ed-Dafili

The driver previously used VCC to calculate the scale, but the datasheet states the output range is fixed by the R_SEL pin (0-30V or 0-60V).

Update probe to read adi,output-range-volts for the scale. Default to the 60V range if the property is missing, while keeping the VCC regulator enable for power.

---
 drivers/iio/dac/ad5504.c | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)
drivers/iio/dac/ad5504.c +16 -10
index 355bcb6a8ba0..1796a9b1e750 100644
@@ -15,6 +15,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/property.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -274,6 +275,7 @@ static int ad5504_probe(struct spi_device *spi)
 	struct iio_dev *indio_dev;
 	struct ad5504_state *st;
 	int ret;
+	u32 val;
 
 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (!indio_dev)
@@ -281,17 +283,21 @@ static int ad5504_probe(struct spi_device *spi)
 
 	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(&spi->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;
-	}
+
+	ret = device_property_read_u32(&spi->dev, "adi,output-range-volts", &val);
+	if (ret)
+		val = 60;
+
+	if (val == 60)
+		st->vref_mv = 60000;
+	else
+		st->vref_mv = 30000;
+
+	if (pdata && pdata->vref_mv)
+		st->vref_mv = pdata->vref_mv;
 
 	st->spi = spi;
 	indio_dev->name = spi_get_device_id(st->spi)->name;
Signature · 1 line
2.47.3
#6 lore raw

Re: [PATCH v1 2/2] iio: dac: ad5504: use adi,output-range-volts for scale calculation

Quoted 6 lines · Taha Ed-Dafili

The driver previously used VCC to calculate the scale, but the datasheet states the output range is fixed by the R_SEL pin (0-30V or 0-60V).

Update probe to read adi,output-range-volts for the scale. Default to the 60V range if the property is missing, while keeping the VCC regulator enable for power.

...

Quoted 4 lines

#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/property.h>

Add it before 'linux/s*.h' includes to make less ordering issues. Ideally one additional patch to sort the headers and one to replace "proxy" headers (following IWYU principle).

...

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 290

Quoted 1 line
drivers/iio/dac/ad5504.c +1 -0
+	ret = device_property_read_u32(&spi->dev, "adi,output-range-volts", &val);

You can pack this into 80 limit with help of

	struct device *dev = &spi->dev;

being defined in the top of the function.

Review

Quoted 2 lines
(quoted diff) +2 -0
+	if (ret)
+		val = 60;

Also this seems an optional, so

	val = 60;
	device_property_read_u32(dev, "adi,output-range-volts", &val);

would be enough.

...

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 295

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	if (val == 60)
+		st->vref_mv = 60000;

60 * MILLI;

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 297

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	else
+		st->vref_mv = 30000;

30 * MILLI;

Needs units.h.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#7 lore raw

Re: [PATCH v1 2/2] iio: dac: ad5504: use adi,output-range-volts for scale calculation

Hi Andy,

Thank you for the detailed feedback, I'll make sure to add those changes in the upcoming v2 series.

Best regards,
Taha

maintainer
#8 lore raw

Re: [PATCH v1 2/2] iio: dac: ad5504: use adi,output-range-volts for scale calculation

Quoted 7 lines · On Fri, 13 Feb 2026 18:05:02 +0100 Taha Ed-Dafili <[email protected]> wrote:

Hi Andy,

Thank you for the detailed feedback, I'll make sure to add those changes in the upcoming v2 series.

Best regards,
Taha

Hi Taha,

Small process thing. Please save thanks like this for the change log on the next version. I know it can feel a little less polite, but if everyone sent a thanks message, that would add at least 1/3rd to the volume of emails and we have too many of those :(

A simple, thanks under the --- or in the cover letter for the next version doesn't have that problem and still acknowledges the inputs of reviewers.

Thanks,

Jonathan

maintainer
#9 lore raw

Re: [PATCH v1 2/2] iio: dac: ad5504: use adi,output-range-volts for scale calculation

In reply to Andy Shevchenko
Quoted 37 lines · On Thu, 12 Feb 2026 22:15:55 +0200 Andy Shevchenko…
Quoted 6 lines · Taha Ed-Dafili

The driver previously used VCC to calculate the scale, but the datasheet states the output range is fixed by the R_SEL pin (0-30V or 0-60V).

Update probe to read adi,output-range-volts for the scale. Default to the 60V range if the property is missing, while keeping the VCC regulator enable for power.

...

Quoted 4 lines

#include <linux/regulator/consumer.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/property.h>

Add it before 'linux/s*.h' includes to make less ordering issues. Ideally one additional patch to sort the headers and one to replace "proxy" headers (following IWYU principle).

...

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 290

Quoted 1 line
drivers/iio/dac/ad5504.c +1 -0
+	ret = device_property_read_u32(&spi->dev, "adi,output-range-volts", &val);  

You can pack this into 80 limit with help of

	struct device *dev = &spi->dev;

being defined in the top of the function.

Review

Quoted 2 lines
(quoted diff) +2 -0
+	if (ret)
+		val = 60;  

Also this seems an optional, so

	val = 60;
	device_property_read_u32(dev, "adi,output-range-volts", &val);
Quoted 8 lines

would be enough.

...

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 295

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	if (val == 60)
+		st->vref_mv = 60000;  

60 * MILLI;

val * MILLI
given it only takes the values 30 and 60 I think. If you want to protect against other values, then check it explicitly rather than everything than isn't 60 being assumed to be 30.

Thanks,

J

Quoted 8 lines

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 297

Quoted 3 lines
drivers/iio/dac/ad5504.c +2 -0
+	else
+		st->vref_mv = 30000;  

30 * MILLI;

Needs units.h.

#10 lore raw

Re: [PATCH v1 2/2] iio: dac: ad5504: use adi,output-range-volts for scale calculation

Quoted 3 lines · Jonathan Cameron
Quoted 1 line · On Thu, 12 Feb 2026 22:15:55 +0200 Andy Shevchenko…

On Thu, Feb 12, 2026 at 07:19:55PM +0100, Taha Ed-Dafili wrote:

...

Quoted 25 lines
Quoted 16 lines

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 290

Quoted 1 line
drivers/iio/dac/ad5504.c +1 -0
+	ret = device_property_read_u32(&spi->dev, "adi,output-range-volts", &val);  

You can pack this into 80 limit with help of

	struct device *dev = &spi->dev;

being defined in the top of the function.

Review

Quoted 2 lines
(quoted diff) +2 -0
+	if (ret)
+		val = 60;  

Also this seems an optional, so

	val = 60;
	device_property_read_u32(dev, "adi,output-range-volts", &val);
Quoted 8 lines

would be enough.

...

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 295

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	if (val == 60)
+		st->vref_mv = 60000;  

60 * MILLI;

Quoted 4 lines

val * MILLI
given it only takes the values 30 and 60 I think. If you want to protect against other values, then check it explicitly rather than everything than isn't 60 being assumed to be 30.

With comment on DT in mind I think this multiplication will gone (as IIUC the DT units is microvolts or so).

Quoted 6 lines
Quoted 6 lines

drivers/iio/dac/ad5504.c static int ad5504_probe(struct spi_device *spi) · line 297

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	else
+		st->vref_mv = 30000;  

30 * MILLI;

Needs units.h.

Signature · 2 lines
With Best Regards,
Andy Shevchenko