Skip to contentSkip to conversation

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

PATCH Superseded Taha Ed-Dafili 5 participants 19 messages Mar 10 – Mar 15

Subsystems (3)

v2 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v2 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, 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).

This series updates the bindings to use standard IIO DAC properties, aligns the driver headers with the IWYU principle, and fixes the core scaling bug while adding support for the hardware's optional GPIOs.

Changes in v2:
- Replaced vendor-specific adi,output-range-volts with the standard output-range-microvolt property array (Krzysztof).
- Replaced adi,output-range-gpios with standard range-sel-gpios (Krzysztof).
- Refactored allOf block in bindings to use not/required logic (Krzysztof).
- Split header updates into two patches: alphabetical sorting and IWYU compliance (Andy).
- Used MILLI and MICRO macros to replace hardcoded values (Andy).
- Used a local dev pointer to respect the 80-character limit and realigned function arguments accordingly (Andy).
- Added driver implementation for the optional CLR and LDAC GPIOs (new in v2)

Thank you to Jonathan Cameron, Krzysztof Kozlowski, Andy Shevchenko, and David Lechner for the reviews, schema guidance, and C optimizations on v1.

Note: I do not have access to the physical AD5504 hardware, so this series has been strictly compile-tested and validated against dt_binding_check based on the datasheet specifications.

Taha Ed-Dafili (5):
dt-bindings: iio: dac: ad5504: add output-range and missing gpios
iio: dac: ad5504: sort headers alphabetically
iio: dac: ad5504: Align headers with IWYU principle
iio: dac: ad5504: fix scale via output-range-microvolt
iio: dac: ad5504: add optional GPIO control for CLR and LDAC

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

PATCH v2 1/5 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.

Use standard output-range-microvolt and range-sel-gpios properties to describe the hardware configuration of the R_SEL pin. Ensure mutual exclusivity using the not/required logic. Additionally, add missing vlogic-supply, clear-gpios, ldac-gpios and datasheet links, and provide a complete usage example.

---
 .../bindings/iio/dac/adi,ad5504.yaml          | 40 ++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +39 -1
index 9c2c038683b4..c0b2d470949a 100644
@@ -10,8 +10,10 @@ maintainers:
   - Lars-Peter Clausen <[email protected]>
   - Jonathan Cameron <[email protected]>
 
-description:
+description: |
   High voltage (up to 60V) DACs with temperature sensor alarm function
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ad5504.pdf
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ad5501.pdf
 
 properties:
   compatible:
@@ -27,16 +29,48 @@ properties:
     maxItems: 1
 
   vcc-supply: true
+  vlogic-supply: true
+
+  output-range-microvolt:
+    description: |
+      Specify the channel output full scale range. The R_SEL pin
+      determines if the range is 0-30V or 0-60V.
+    items:
+      - const: 0
+      - enum: [30000000, 60000000]
+    default: [0, 60000000]
+
+  range-sel-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:
+  - not:
+      required:
+        - range-sel-gpios
+        - output-range-microvolt
 
 examples:
   - |
     #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+
     spi {
         #address-cells = <1>;
         #size-cells = <0>;
@@ -45,6 +79,10 @@ examples:
             compatible = "adi,ad5504";
             vcc-supply = <&dac_vcc>;
             interrupts = <55 IRQ_TYPE_EDGE_FALLING>;
+
+            output-range-microvolt = <0 60000000>;
+            clear-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
+            ldac-gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
         };
     };
 ...
Signature · 1 line
2.47.3
#2 lore raw

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

Quoted 10 lines · Taha Ed-Dafili

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

Use standard output-range-microvolt and range-sel-gpios properties to describe the hardware configuration of the R_SEL pin. Ensure mutual exclusivity using the not/required logic. Additionally, add missing vlogic-supply, clear-gpios, ldac-gpios and datasheet links, and provide a complete usage example.

Hm? Where did I suggest writing such patch?

Are you mixing terms here? I gave you review, no?

Quoted 45 lines
---
 .../bindings/iio/dac/adi,ad5504.yaml          | 40 ++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +23 -1
index 9c2c038683b4..c0b2d470949a 100644
@@ -10,8 +10,10 @@ maintainers:
   - Lars-Peter Clausen <[email protected]>
   - Jonathan Cameron <[email protected]>
 
-description:
+description: |
   High voltage (up to 60V) DACs with temperature sensor alarm function
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ad5504.pdf
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ad5501.pdf
 
 properties:
   compatible:
@@ -27,16 +29,48 @@ properties:
     maxItems: 1
 
   vcc-supply: true
+  vlogic-supply: true
+
+  output-range-microvolt:
+    description: |
+      Specify the channel output full scale range. The R_SEL pin
+      determines if the range is 0-30V or 0-60V.
+    items:
+      - const: 0
+      - enum: [30000000, 60000000]
+    default: [0, 60000000]
+
+  range-sel-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
+

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

Quoted 10 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +4 -0
+  ldac-gpios:
+    description: GPIO that controls the /LDAC pin (active low).
+    maxItems: 1
 
 additionalProperties: false
 
 required:
   - compatible
   - reg
+  - vcc-supply

This is technically ABI break and nothing in the commit msg explained why you are doing this, why this was not required before etc. Changes you make must come with proper background.

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

Quoted 6 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +6 -0
+
+allOf:
+  - not:
+      required:
+        - range-sel-gpios
+        - output-range-microvolt

Best regards,
Krzysztof

#3 lore raw

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

Hi Krzysztof,

I misunderstood how the Suggested-by tag is used. Since
Andy explicitly asked me to sort the headers, and the DT properties were provided during the v1 review, I thought I should credit those direct suggestions. My reasoning was simply that those specific patches and changes wouldn't exist in this series without that feedback.

I now realize this tag is meant for original feature ideas, not standard review feedback. I will drop the tags across the entire series in v3.

Regarding vcc-supply: I made it required because the driver currently fails to probe without it. I understand now that this causes an ABI break, so I will revert it back to optional in v3.

Thank you for the clarification.

Best regards,
Taha

maintainer
#4 lore raw

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

Quoted 8 lines · On Wed, 11 Mar 2026 09:49:02 +0000 Taha Ed-Dafili <[email protected]> wrote:

Hi Krzysztof,

I misunderstood how the Suggested-by tag is used. Since
Andy explicitly asked me to sort the headers, and the DT properties were provided during the v1 review, I thought I should credit those direct suggestions. My reasoning was simply that those specific patches and changes wouldn't exist in this series without that feedback.

Quoted 6 lines

I now realize this tag is meant for original feature ideas, not standard review feedback. I will drop the tags across the entire series in v3.

Regarding vcc-supply: I made it required because the driver currently fails to probe without it. I understand now that this causes an ABI break, so I will revert it back to optional in v3.

Are you sure it fails to probe?

	ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
	if (ret < 0 && ret != -ENODEV)
		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;
	}

If it's not provided we should get ret == -ENODEV then fall through to the other paths to either get it or warn if it's not there.

Logically it is required, but we have been papering over the DT binding not listing that for a while.

Jonathan

Quoted 5 lines

Thank you for the clarification.

Best regards,
Taha

#5 lore raw

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

In reply to Taha Ed-Dafili
Quoted 43 lines · Taha Ed-Dafili

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

Use standard output-range-microvolt and range-sel-gpios properties to describe the hardware configuration of the R_SEL pin. Ensure mutual exclusivity using the not/required logic. Additionally, add missing vlogic-supply, clear-gpios, ldac-gpios and datasheet links, and provide a complete usage example.

---
 .../bindings/iio/dac/adi,ad5504.yaml          | 40 ++++++++++++++++++-

 1 file changed, 39 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +0 -0
index 9c2c038683b4..c0b2d470949a 100644
@@ -10,8 +10,10 @@ maintainers:

   - Lars-Peter Clausen <[email protected]>
   - Jonathan Cameron <[email protected]>

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +1 -1
-description:
+description: |

   High voltage (up to 60V) DACs with temperature sensor alarm function +  https://www.analog.com/media/en/technical-documentation/data-sheets/ad5504.pdf
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ad5501.pdf

 properties:
   compatible:

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +0 -0
@@ -27,16 +29,48 @@ properties:

     maxItems: 1

   vcc-supply: true
+  vlogic-supply: true

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +6 -0
+
+  output-range-microvolt:
+    description: |
+      Specify the channel output full scale range. The R_SEL pin
+      determines if the range is 0-30V or 0-60V.
+    items:

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

Quoted 10 lines
Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +10 -0
+      - const: 0
+      - enum: [30000000, 60000000]
+    default: [0, 60000000]
+
+  range-sel-gpios:
+    description:
+      GPIO connected to the R_SEL pin to select the output voltage range.
+    maxItems: 1
+
+  clear-gpios:

I would match the datasheet name. So clr.

- Nuno Sá

Quoted 39 lines

+    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

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +6 -0
+
+allOf:
+  - not:
+      required:
+        - range-sel-gpios
+        - output-range-microvolt


 examples:
   - |
     #include <dt-bindings/interrupt-controller/irq.h> +    #include <dt-bindings/gpio/gpio.h>
+
     spi {
         #address-cells = <1>;
         #size-cells = <0>;

Documentation/devicetree/bindings/iio/dac/adi,ad5504.yaml +4 -0
@@ -45,6 +79,10 @@ examples:
              compatible = "adi,ad5504";
              vcc-supply = <&dac_vcc>;
              interrupts = <55 IRQ_TYPE_EDGE_FALLING>;
+
+            output-range-microvolt = <0 60000000>;
+            clear-gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
+            ldac-gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
          };
      };
...
#6 lore raw

PATCH v2 2/5 iio: dac: ad5504: sort headers alphabetically

In reply to Taha Ed-Dafili

Rearrange the include headers in alphabetical order to follow the standard kernel coding style. This is a preparatory cleanup with no functional changes.

---
 drivers/iio/dac/ad5504.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/iio/dac/ad5504.c +6 -6
index 355bcb6a8ba0..20a36e4a389e 100644
@@ -5,16 +5,16 @@
  * Copyright 2011 Analog Devices Inc.
  */
 
-#include <linux/interrupt.h>
-#include <linux/fs.h>
+#include <linux/bitops.h>
 #include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/spi/spi.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/spi/spi.h>
 #include <linux/sysfs.h>
-#include <linux/regulator/consumer.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
Signature · 1 line
2.47.3
Reviewed-by on v2 2/5
#7 lore raw

Re: [PATCH v2 2/5] iio: dac: ad5504: sort headers alphabetically

Quoted 3 lines · Taha Ed-Dafili

Rearrange the include headers in alphabetical order to follow the standard kernel coding style. This is a preparatory cleanup with no functional changes.

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

Re: [PATCH v2 2/5] iio: dac: ad5504: sort headers alphabetically

Quoted 8 lines · On Tue, 10 Mar 2026 21:15:16 +0100 Krzysztof Kozlowski <[email protected]> wrote:
Quoted 5 lines · Taha Ed-Dafili

Rearrange the include headers in alphabetical order to follow the standard kernel coding style. This is a preparatory cleanup with no functional changes.

Where was this patch suggested by Andy?

https://lore.kernel.org/all/[email protected]/

It's one of Andy's favourite bits or 'whilst you are here feedback' and was given for this specific driver.

Quoted 3 lines

Best regards,
Krzysztof

#10 lore raw

PATCH v2 3/5 iio: dac: ad5504: Align headers with IWYU principle

In reply to Taha Ed-Dafili

Update the header inclusions to follow the IWYU principle.

- Remove <linux/fs.h> and <linux/slab.h> as they are unused. The driver relies on devm_ managed allocations, so slab is not required.

- Replace <linux/bitops.h> with <linux/bits.h> as only the BIT() and GENMASK() macros are used.

- Add <linux/mod_devicetable.h> for struct spi_device_id.

- Add <linux/errno.h> and <linux/types.h> for error codes and data types.

---
 drivers/iio/dac/ad5504.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/iio/dac/ad5504.c +4 -3
index 20a36e4a389e..e71218c44982 100644
@@ -5,16 +5,17 @@
  * Copyright 2011 Analog Devices Inc.
  */
 
-#include <linux/bitops.h>
+#include <linux/bits.h>
 #include <linux/device.h>
-#include <linux/fs.h>
+#include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
-#include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/sysfs.h>
+#include <linux/types.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
Signature · 1 line
2.47.3
#11 lore raw

Re: [PATCH v2 3/5] iio: dac: ad5504: Align headers with IWYU principle

Quoted 4 lines · Taha Ed-Dafili

Update the header inclusions to follow the IWYU principle.

- Remove <linux/fs.h> and <linux/slab.h> as they are unused. The driver relies on devm_ managed allocations, so slab is not required.

...

drivers/iio/dac/ad5504.c

Quoted 4 lines
drivers/iio/dac/ad5504.c +1 -1
-#include <linux/bitops.h>
+#include <linux/bits.h>
 
 #include <linux/device.h>

Is this still being used directly.

drivers/iio/dac/ad5504.c

Quoted 5 lines
drivers/iio/dac/ad5504.c +1 -1
-#include <linux/fs.h>
+#include <linux/errno.h>
 #include <linux/interrupt.h>
 
 #include <linux/kernel.h>

And what is this for?

drivers/iio/dac/ad5504.c line 18

Quoted 7 lines
drivers/iio/dac/ad5504.c +2 -1
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
-#include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/sysfs.h>
+#include <linux/types.h>

The rest of the changes looks correct, but still missing headers:
linux/kstrtox.h

asm/byteorder.h

Might be more.

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

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

In reply to Taha Ed-Dafili

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.

---
 drivers/iio/dac/ad5504.c | 43 ++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 19 deletions(-)
drivers/iio/dac/ad5504.c +24 -19
index e71218c44982..cd563460fc0a 100644
@@ -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[] = {
Signature · 1 line
2.47.3
#13 lore raw

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

Quoted 8 lines · Taha Ed-Dafili

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.

...

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 281

Quoted 9 lines

static int ad5504_probe(struct spi_device *spi)
{

drivers/iio/dac/ad5504.c +3 -1
-	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];

Preserve the reversed xmas tree order.

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 283

Quoted 2 lines
drivers/iio/dac/ad5504.c +1 -1
-	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));

Unrelated change. This should be split into another patch that makes use of it here and there.

I have a déjà vu about these comments...

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = {

Quoted 12 lines
drivers/iio/dac/ad5504.c +2 -3
 	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) {

Why remove this condition?

This might break use of the driver on ACPI systems.

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 295

Quoted 11 lines
drivers/iio/dac/ad5504.c +4 -7
-		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);

ARRAY_SIZE()
(will require array_size.h)

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 297

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	if (!ret && range[1] == 30 * MICRO)
+		st->vref_mv = 30 * MILLI;

This looks unusual and hard to follow. It also misses the validation of the min of the range.

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 300

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

No, pdata should go.

Quoted 3 lines
drivers/iio/dac/ad5504.c +0 -0
 	st->spi = spi;
 	indio_dev->name = spi_get_device_id(st->spi)->name;

...

Quoted 12 lines
drivers/iio/dac/ad5504.c +3 -6
 	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,

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

Quoted 10 lines
drivers/iio/dac/ad5504.c +4 -1
+						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);
 }

Unrelated changes.

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

Re: [PATCH v2 3/5] iio: dac: ad5504: Align headers with IWYU principle

Hi Andy,

Thank you for the detailed review across the series.

Quoted 2 lines
Quoted 1 line

#include <linux/device.h>

Is this still being used directly.

Yes, it is still needed for struct device and dev_get_platdata().

Quoted 2 lines
Quoted 1 line

#include <linux/kernel.h>

And what is this for?

You are right, this appears to be a leftover. I will double-check its usage and drop it in v3 if it's no longer needed.

Quoted 6 lines

The rest of the changes looks correct, but still missing headers:
linux/kstrtox.h

asm/byteorder.h

Might be more.

Good catch on these. I will add <asm/byteorder.h> (for cpu_to_be16()) and <linux/kstrtox.h>. I will also do another general pass over the includes to better align with IWYU principles before sending v3.

Regarding the probe function (Patch 4):

I will split the struct device *dev = &spi->dev; refactoring into its own preparatory patch. For the scale calculation, I will restore the -ENODEV check to maintain ACPI compatibility, use ARRAY_SIZE() (adding <linux/array_size.h>), validate the range array indices properly, and drop the legacy pdata fallback.

I will include all of these fixes in v3.

Best regards,
Taha

#15 lore raw

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

In reply to Andy Shevchenko
Quoted 64 lines · Andy Shevchenko
Quoted 8 lines · Taha Ed-Dafili

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.

...

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 281

Quoted 9 lines

 static int ad5504_probe(struct spi_device *spi)
 {

drivers/iio/dac/ad5504.c +2 -1
-	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;

drivers/iio/dac/ad5504.c +1 -0
+	u32 range[2];

Preserve the reversed xmas tree order.

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 283

Quoted 2 lines
drivers/iio/dac/ad5504.c +1 -1
-	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));

Unrelated change. This should be split into another patch that makes use of it here and there.

I have a déjà vu about these comments...

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 288

Quoted 12 lines

  if (!indio_dev)
  return -ENOMEM;

  st = iio_priv(indio_dev);

drivers/iio/dac/ad5504.c +2 -2
-	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;

drivers/iio/dac/ad5504.c +0 -1
-	if (ret == -ENODEV) {

Why remove this condition?

This might break use of the driver on ACPI systems.

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 295

Quoted 11 lines
drivers/iio/dac/ad5504.c +4 -7
-		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);

ARRAY_SIZE()
(will require array_size.h)

Quoted 5 lines

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 297

Quoted 2 lines
drivers/iio/dac/ad5504.c +2 -0
+	if (!ret && range[1] == 30 * MICRO)
+		st->vref_mv = 30 * MILLI;

This looks unusual and hard to follow. It also misses the validation of the min of the range.

And the max FWIW. If the property is given we should be strict about it and make sure only valid inputs are given.

- Nuno Sá

Quoted 36 lines

drivers/iio/dac/ad5504.c static const struct iio_chan_spec ad5504_channels[] = { · line 300

Quoted 3 lines
drivers/iio/dac/ad5504.c +2 -0
+	if (pdata && pdata->vref_mv)
+		st->vref_mv = pdata->vref_mv;

No, pdata should go.

Quoted 3 lines


  st->spi = spi;
  indio_dev->name = spi_get_device_id(st->spi)->name;

...

Quoted 21 lines

  indio_dev->modes = INDIO_DIRECT_MODE;

  if (spi->irq) {

drivers/iio/dac/ad5504.c +6 -6
-		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;
  }

drivers/iio/dac/ad5504.c +1 -1
-	return devm_iio_device_register(&spi->dev, indio_dev);
+	return devm_iio_device_register(dev, indio_dev);
Quoted 1 line

 }

Unrelated changes.

#16 lore raw

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

In reply to Taha Ed-Dafili
Quoted 11 lines · Taha Ed-Dafili

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.

Where were these suggestions given?

Best regards,
Krzysztof

#17 lore raw

PATCH v2 5/5 iio: dac: ad5504: add optional GPIO control for CLR and LDAC

In reply to Taha Ed-Dafili

Add support for the optional 'clear-gpios' and 'ldac-gpios' properties defined in the device tree bindings.

Use devm_gpiod_get_optional() with GPIOD_OUT_LOW to ensure the pins are initialized to their inactive state.

---
 drivers/iio/dac/ad5504.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/iio/dac/ad5504.c +14 -0
index cd563460fc0a..58538f5263fc 100644
@@ -7,7 +7,9 @@
 
 #include <linux/bits.h>
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mod_devicetable.h>
@@ -48,6 +50,8 @@
  * @vref_mv:		actual reference voltage used
  * @pwr_down_mask:	power down mask
  * @pwr_down_mode:	current power down mode
+ * @gpio_clear:	GPIO descriptor for the /CLR pin
+ * @gpio_ldac:		GPIO descriptor for the /LDAC pin
  * @data:		transfer buffer
  */
 struct ad5504_state {
@@ -56,6 +60,8 @@ struct ad5504_state {
 	unsigned short			vref_mv;
 	unsigned			pwr_down_mask;
 	unsigned			pwr_down_mode;
+	struct gpio_desc		*gpio_clear;
+	struct gpio_desc		*gpio_ldac;
 
 	__be16				data[2] __aligned(IIO_DMA_MINALIGN);
 };
@@ -299,6 +305,14 @@ static int ad5504_probe(struct spi_device *spi)
 	if (pdata && pdata->vref_mv)
 		st->vref_mv = pdata->vref_mv;
 
+	st->gpio_clear = devm_gpiod_get_optional(dev, "clear", GPIOD_OUT_LOW);
+	if (IS_ERR(st->gpio_clear))
+		return PTR_ERR(st->gpio_clear);
+
+	st->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_LOW);
+	if (IS_ERR(st->gpio_ldac))
+		return PTR_ERR(st->gpio_ldac);
+
 	st->spi = spi;
 	indio_dev->name = spi_get_device_id(st->spi)->name;
 	indio_dev->info = &ad5504_info;
Signature · 1 line
2.47.3
#18 lore raw

Re: [PATCH v2 5/5] iio: dac: ad5504: add optional GPIO control for CLR and LDAC

Quoted 47 lines · Taha Ed-Dafili

Add support for the optional 'clear-gpios' and 'ldac-gpios' properties defined in the device tree bindings.

Use devm_gpiod_get_optional() with GPIOD_OUT_LOW to ensure the pins are initialized to their inactive state.

---
 drivers/iio/dac/ad5504.c | 14 ++++++++++++++

 1 file changed, 14 insertions(+)
drivers/iio/dac/ad5504.c +0 -0
index cd563460fc0a..58538f5263fc 100644
@@ -7,7 +7,9 @@


 #include <linux/bits.h>
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mod_devicetable.h>

drivers/iio/dac/ad5504.c +4 -0
@@ -48,6 +50,8 @@
   * @vref_mv:		actual reference voltage used
   * @pwr_down_mask:	power down mask
   * @pwr_down_mode:	current power down mode
+ * @gpio_clear:	GPIO descriptor for the /CLR pin
+ * @gpio_ldac:		GPIO descriptor for the /LDAC pin
   * @data:		transfer buffer
   */
  struct ad5504_state {
@@ -56,6 +60,8 @@ struct ad5504_state {
  	unsigned short			vref_mv;
  	unsigned			pwr_down_mask;
  	unsigned			pwr_down_mode;
+	struct gpio_desc		*gpio_clear;
+	struct gpio_desc		*gpio_ldac;


  __be16 data[2] __aligned(IIO_DMA_MINALIGN);
 };

drivers/iio/dac/ad5504.c +0 -0
@@ -299,6 +305,14 @@ static int ad5504_probe(struct spi_device *spi)
  	if (pdata && pdata->vref_mv)
  		st->vref_mv = pdata->vref_mv;

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

Quoted 8 lines
drivers/iio/dac/ad5504.c +8 -0
+	st->gpio_clear = devm_gpiod_get_optional(dev, "clear", GPIOD_OUT_LOW);
+	if (IS_ERR(st->gpio_clear))
+		return PTR_ERR(st->gpio_clear);
+
+	st->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_LOW);
+	if (IS_ERR(st->gpio_ldac))
+		return PTR_ERR(st->gpio_ldac);
+

Fine having the above in bindings but as it stands now, not seeing the purpose of having it in the driver. We're not handling these gpios at all.

- Nuno Sá

Quoted 1 line