[PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910

Rodrigo Alencar via B4 Relay posted 8 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Rodrigo Alencar via B4 Relay 1 month, 1 week ago
From: Rodrigo Alencar <rodrigo.alencar@analog.com>

DT-bindings for AD9910, a 1 GSPS DDS with 14-bit DAC. It includes
configurations for the reference clock path, DAC current, reset and basic
GPIO control.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
---
 .../bindings/iio/frequency/adi,ad9910.yaml         | 236 +++++++++++++++++++++
 MAINTAINERS                                        |   7 +
 2 files changed, 243 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
new file mode 100644
index 000000000000..43b21d1428ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
@@ -0,0 +1,236 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/frequency/adi,ad9910.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD9910 Direct Digital Synthesizer
+
+maintainers:
+  - Rodrigo Alencar <rodrigo.alencar@analog.com>
+
+description:
+  The AD9910 is a 1 GSPS direct digital synthesizer (DDS) with an integrated
+  14-bit DAC. It features single tone mode with 8 configurable profiles,
+  a digital ramp generator, RAM control, OSK, and a parallel data port for
+  high-speed streaming.
+
+  https://www.analog.com/en/products/ad9910.html
+
+properties:
+  compatible:
+    const: adi,ad9910
+
+  reg:
+    maxItems: 1
+
+  spi-max-frequency:
+    maximum: 70000000
+
+  clocks:
+    maxItems: 1
+    description:
+      Reference clock input (REFCLK). When the PLL is enabled, this is
+      multiplied by adi,pll-multiplier to produce the system clock.
+      When the PLL is bypassed, the reference clock is used directly or divided
+      by 2 based on adi,reference-div2-enable to produce the system clock.
+
+  dvdd-io33-supply:
+    description: 3.3V Digital I/O supply.
+
+  avdd33-supply:
+    description: 3.3V Analog DAC supply.
+
+  dvdd18-supply:
+    description: 1.8V Digital Core supply.
+
+  avdd18-supply:
+    description: 1.8V Analog Core supply.
+
+  resets:
+    minItems: 1
+    maxItems: 2
+
+  reset-names:
+    oneOf:
+      - items:
+          - const: dev
+      - items:
+          - const: dev
+          - const: io
+
+  reset-gpios:
+    maxItems: 2
+    description:
+      GPIOs controlling the device reset and the I/O_RESET pins. This is only
+      used if resets property is not defined.
+
+  powerdown-gpios:
+    maxItems: 1
+    description:
+      GPIO controlling the EXT_PWR_DWN pin.
+
+  update-gpios:
+    maxItems: 1
+    description:
+      GPIO controlling the I/O_UPDATE pin.
+
+  profile-gpios:
+    minItems: 3
+    maxItems: 3
+    description:
+      GPIOs controlling the PROFILE[2:0] pins for profile selection.
+
+  adi,pll-multiplier:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 12
+    maximum: 127
+    description:
+      PLL feedback divider value (N). The system clock frequency is
+      REFCLK * N. When not specified, the PLL is bypassed.
+
+  adi,pll-vco-select:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 5
+    description: |
+      VCO frequency range selection (0-5). When not specified and the PLL
+      is enabled, the VCO range is automatically selected based on the
+      computed system clock frequency. Typical VCO frequency ranges are:
+      - Range 0: 370 MHz to 510 MHz (Auto-selected when <= 465 MHz)
+      - Range 1: 420 MHz to 590 MHz (Auto-selected when > 465 MHz and <= 545 MHz)
+      - Range 2: 500 MHz to 700 MHz (Auto-selected when > 545 MHz and <= 650 MHz)
+      - Range 3: 600 MHz to 880 MHz (Auto-selected when > 650 MHz and <= 790 MHz)
+      - Range 4: 700 MHz to 950 MHz (Auto-selected when > 790 MHz and <= 885 MHz)
+      - Range 5: 820 MHz to 1050 MHz (Auto-selected when > 885 MHz)
+
+  adi,charge-pump-current-microamp:
+    minimum: 212
+    maximum: 387
+    default: 387
+    description:
+      PLL charge pump current in microamps. Only applicable when the PLL
+      is enabled. The value is rounded to the nearest supported step.
+
+  adi,refclk-out-drive-strength:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [ disabled, low, medium, high ]
+    default: disabled
+    description:
+      Reference clock output (DRV0) drive strength. Only applicable when
+      the PLL is enabled.
+
+  adi,reference-div2-enable:
+    type: boolean
+    description:
+      Enable the reference clock input divider. When enabled, the input
+      reference frequency is halved before deriving the system clock.
+      This is only applicable when the PLL is bypassed.
+
+  adi,inverse-sinc-enable:
+    type: boolean
+    description:
+      Enable the inverse sinc filter that compensates for the sinc roll-off
+      of the DAC output. When it is enabled, the filter introduces up to 3 dB
+      of insertion loss.
+
+  adi,sine-output-enable:
+    type: boolean
+    description:
+      Select sine wave output from the DDS core. When not set, the
+      output is a cosine wave.
+
+  adi,sync-clk-disable:
+    type: boolean
+    description:
+      Disable the SYNC_CLK output pin. SYNC_CLK runs at one quarter
+      of the system clock frequency.
+
+  adi,pdclk-disable:
+    type: boolean
+    description:
+      Disable the parallel data clock (PDCLK) output. PDCLK runs at
+      one quarter of the system clock frequency.
+
+  adi,pdclk-invert:
+    type: boolean
+    description:
+      Invert the polarity of the PDCLK output.
+
+  adi,tx-enable-invert:
+    type: boolean
+    description:
+      Invert the polarity of the TX_ENABLE input pin.
+
+  adi,dac-output-current-microamp:
+    minimum: 8640
+    maximum: 31590
+    default: 20070
+    description:
+      DAC full-scale output current in microamps.
+
+dependencies:
+  adi,pll-vco-select: [ 'adi,pll-multiplier' ]
+  adi,charge-pump-current-microamp: [ 'adi,pll-multiplier' ]
+  adi,refclk-out-drive-strength: [ 'adi,pll-multiplier' ]
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - dvdd-io33-supply
+  - avdd33-supply
+  - dvdd18-supply
+  - avdd18-supply
+
+dependentSchemas:
+  resets:
+    properties:
+      reset-gpios: false
+  reset-gpios:
+    properties:
+      resets: false
+  adi,reference-div2-enable:
+    properties:
+      adi,pll-multiplier: false
+  adi,pll-multiplier:
+    properties:
+      adi,reference-div2-enable: false
+
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        dds@0 {
+            compatible = "adi,ad9910";
+            reg = <0>;
+            spi-max-frequency = <1000000>;
+            clocks = <&ad9910_refclk>;
+
+            dvdd-io33-supply = <&vdd_io33>;
+            avdd33-supply = <&vdd_a33>;
+            dvdd18-supply = <&vdd_d18>;
+            avdd18-supply = <&vdd_a18>;
+
+            reset-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>,
+                          <&gpio 1 GPIO_ACTIVE_HIGH>;
+            powerdown-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
+            update-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
+            profile-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>,
+                            <&gpio 5 GPIO_ACTIVE_HIGH>,
+                            <&gpio 6 GPIO_ACTIVE_HIGH>;
+
+            adi,pll-multiplier = <40>;
+            adi,charge-pump-current-microamp = <387>;
+            adi,refclk-out-drive-strength = "disabled";
+            adi,inverse-sinc-enable;
+        };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 1251965d70bd..79b4180e2334 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1610,6 +1610,13 @@ W:	https://ez.analog.com/linux-software-drivers
 F:	Documentation/devicetree/bindings/iio/dac/adi,ad9739a.yaml
 F:	drivers/iio/dac/ad9739a.c
 
+ANALOG DEVICES INC AD9910 DRIVER
+M:	Rodrigo Alencar <rodrigo.alencar@analog.com>
+L:	linux-iio@vger.kernel.org
+S:	Supported
+W:	https://ez.analog.com/linux-software-drivers
+F:	Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
+
 ANALOG DEVICES INC MAX22007 DRIVER
 M:	Janani Sunil <janani.sunil@analog.com>
 L:	linux-iio@vger.kernel.org

-- 
2.43.0
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Jonathan Cameron 1 month ago
On Fri, 20 Feb 2026 16:46:05 +0000
Rodrigo Alencar via B4 Relay <devnull+rodrigo.alencar.analog.com@kernel.org> wrote:

> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
> 
> DT-bindings for AD9910, a 1 GSPS DDS with 14-bit DAC. It includes
> configurations for the reference clock path, DAC current, reset and basic
> GPIO control.
> 
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Hi Rodrigo,

A few comments from me inline.

Thanks,

Jonathan

> ---
>  .../bindings/iio/frequency/adi,ad9910.yaml         | 236 +++++++++++++++++++++
>  MAINTAINERS                                        |   7 +
>  2 files changed, 243 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> new file mode 100644
> index 000000000000..43b21d1428ba
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml

> +  adi,pll-vco-select:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 5
> +    description: |
> +      VCO frequency range selection (0-5). When not specified and the PLL
> +      is enabled, the VCO range is automatically selected based on the
> +      computed system clock frequency. Typical VCO frequency ranges are:

Given this automatic mode. Why would need to override it?

> +      - Range 0: 370 MHz to 510 MHz (Auto-selected when <= 465 MHz)
> +      - Range 1: 420 MHz to 590 MHz (Auto-selected when > 465 MHz and <= 545 MHz)
> +      - Range 2: 500 MHz to 700 MHz (Auto-selected when > 545 MHz and <= 650 MHz)
> +      - Range 3: 600 MHz to 880 MHz (Auto-selected when > 650 MHz and <= 790 MHz)
> +      - Range 4: 700 MHz to 950 MHz (Auto-selected when > 790 MHz and <= 885 MHz)
> +      - Range 5: 820 MHz to 1050 MHz (Auto-selected when > 885 MHz)
> +
> +  adi,charge-pump-current-microamp:
> +    minimum: 212
> +    maximum: 387
> +    default: 387
> +    description:
> +      PLL charge pump current in microamps. Only applicable when the PLL
> +      is enabled. The value is rounded to the nearest supported step.
> +
> +  adi,refclk-out-drive-strength:
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum: [ disabled, low, medium, high ]
> +    default: disabled
> +    description:
> +      Reference clock output (DRV0) drive strength. Only applicable when
> +      the PLL is enabled.
> +
> +  adi,reference-div2-enable:
> +    type: boolean
> +    description:
> +      Enable the reference clock input divider. When enabled, the input
> +      reference frequency is halved before deriving the system clock.
> +      This is only applicable when the PLL is bypassed.
Often for these they can be derived from what the desired output
frequencies are. There tends to be a right answer for any combination on
input clocks and output frequency so we don't normally need them
in DT. If there is a reason we do here, needs more explanation.

> +
> +  adi,inverse-sinc-enable:
> +    type: boolean
> +    description:
> +      Enable the inverse sinc filter that compensates for the sinc roll-off
> +      of the DAC output. When it is enabled, the filter introduces up to 3 dB
> +      of insertion loss.

We probably need to improve our userspace filter controls for this one.
Why would it need to be in DT?  Maybe we even just decide to always
enable this one despite the attenuation.  I'm not sure how the term
insertion loss applies to a filter being enabled or not.

> +
> +  adi,sine-output-enable:
> +    type: boolean
> +    description:
> +      Select sine wave output from the DDS core. When not set, the
> +      output is a cosine wave.

That sounds like a userspace thing probably represented as a phase
offset.

> +
> +  adi,sync-clk-disable:
> +    type: boolean
> +    description:
> +      Disable the SYNC_CLK output pin. SYNC_CLK runs at one quarter
> +      of the system clock frequency.
> +
> +  adi,pdclk-disable:
> +    type: boolean
> +    description:
> +      Disable the parallel data clock (PDCLK) output. PDCLK runs at
> +      one quarter of the system clock frequency.
> +
> +  adi,pdclk-invert:
> +    type: boolean
> +    description:
> +      Invert the polarity of the PDCLK output.

Others have commented on these as clock providers. I think that
will make more sense.

> +
> +  adi,tx-enable-invert:
> +    type: boolean
> +    description:
> +      Invert the polarity of the TX_ENABLE input pin.

It's an input, so I assume you are referring to some chip control
that allows us to change what is expected on this pin from
active high to active low or similar?

Is this hooked up to the backend fpga signal and that has some
fixed output polarity?

> +
> +  adi,dac-output-current-microamp:
> +    minimum: 8640
> +    maximum: 31590
> +    default: 20070
> +    description:
> +      DAC full-scale output current in microamps.

Needs an explanation of why this is in DT.
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by David Lechner 1 month, 1 week ago
On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:
> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
> 
> DT-bindings for AD9910, a 1 GSPS DDS with 14-bit DAC. It includes
> configurations for the reference clock path, DAC current, reset and basic
> GPIO control.
> 
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
> ---
>  .../bindings/iio/frequency/adi,ad9910.yaml         | 236 +++++++++++++++++++++
>  MAINTAINERS                                        |   7 +
>  2 files changed, 243 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> new file mode 100644
> index 000000000000..43b21d1428ba
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> @@ -0,0 +1,236 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/frequency/adi,ad9910.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Analog Devices AD9910 Direct Digital Synthesizer
> +
> +maintainers:
> +  - Rodrigo Alencar <rodrigo.alencar@analog.com>
> +
> +description:
> +  The AD9910 is a 1 GSPS direct digital synthesizer (DDS) with an integrated
> +  14-bit DAC. It features single tone mode with 8 configurable profiles,
> +  a digital ramp generator, RAM control, OSK, and a parallel data port for
> +  high-speed streaming.
> +
> +  https://www.analog.com/en/products/ad9910.html
> +
> +properties:
> +  compatible:
> +    const: adi,ad9910
> +
> +  reg:
> +    maxItems: 1
> +
> +  spi-max-frequency:
> +    maximum: 70000000
> +
> +  clocks:
> +    maxItems: 1
> +    description:
> +      Reference clock input (REFCLK). When the PLL is enabled, this is
> +      multiplied by adi,pll-multiplier to produce the system clock.
> +      When the PLL is bypassed, the reference clock is used directly or divided
> +      by 2 based on adi,reference-div2-enable to produce the system clock.

Devicetree is just concerned with how it is wired up. The first
sentence is enough.

> +
> +  dvdd-io33-supply:
> +    description: 3.3V Digital I/O supply.
> +
> +  avdd33-supply:
> +    description: 3.3V Analog DAC supply.
> +
> +  dvdd18-supply:
> +    description: 1.8V Digital Core supply.
> +
> +  avdd18-supply:
> +    description: 1.8V Analog Core supply.
> +
> +  resets:
> +    minItems: 1
> +    maxItems: 2
> +
> +  reset-names:
> +    oneOf:
> +      - items:
> +          - const: dev
> +      - items:
> +          - const: dev
> +          - const: io

This could be a bit more clear. Does dev == MASTER_RESET pin?
And what about DAC_RSET?

> +
> +  reset-gpios:
> +    maxItems: 2
> +    description:
> +      GPIOs controlling the device reset and the I/O_RESET pins. This is only
> +      used if resets property is not defined.
> +
> +  powerdown-gpios:
> +    maxItems: 1
> +    description:
> +      GPIO controlling the EXT_PWR_DWN pin.
> +
> +  update-gpios:
> +    maxItems: 1
> +    description:
> +      GPIO controlling the I/O_UPDATE pin.
> +
> +  profile-gpios:
> +    minItems: 3
> +    maxItems: 3
> +    description:
> +      GPIOs controlling the PROFILE[2:0] pins for profile selection.
> +

Looks like possibly some interrupts as well: RAM_SWP_OVR and SYNC_SMP_ERR

> +  adi,pll-multiplier:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 12
> +    maximum: 127
> +    description:
> +      PLL feedback divider value (N). The system clock frequency is
> +      REFCLK * N. When not specified, the PLL is bypassed.

What determines the value that should be selected here? This doesn't seem like
something we would normally put in the devicetree. (Smells like configuration
rather than describing what is wired up.)

> +
> +  adi,pll-vco-select:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 5
> +    description: |
> +      VCO frequency range selection (0-5). When not specified and the PLL
> +      is enabled, the VCO range is automatically selected based on the
> +      computed system clock frequency. Typical VCO frequency ranges are:
> +      - Range 0: 370 MHz to 510 MHz (Auto-selected when <= 465 MHz)
> +      - Range 1: 420 MHz to 590 MHz (Auto-selected when > 465 MHz and <= 545 MHz)
> +      - Range 2: 500 MHz to 700 MHz (Auto-selected when > 545 MHz and <= 650 MHz)
> +      - Range 3: 600 MHz to 880 MHz (Auto-selected when > 650 MHz and <= 790 MHz)
> +      - Range 4: 700 MHz to 950 MHz (Auto-selected when > 790 MHz and <= 885 MHz)
> +      - Range 5: 820 MHz to 1050 MHz (Auto-selected when > 885 MHz)
> +

Same here. How does this depend on how the chip is wired up?

> +  adi,charge-pump-current-microamp:
> +    minimum: 212
> +    maximum: 387
> +    default: 387
> +    description:
> +      PLL charge pump current in microamps. Only applicable when the PLL
> +      is enabled. The value is rounded to the nearest supported step.
> +
> +  adi,refclk-out-drive-strength:
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum: [ disabled, low, medium, high ]
> +    default: disabled
> +    description:
> +      Reference clock output (DRV0) drive strength. Only applicable when
> +      the PLL is enabled.
> +
> +  adi,reference-div2-enable:
> +    type: boolean
> +    description:
> +      Enable the reference clock input divider. When enabled, the input
> +      reference frequency is halved before deriving the system clock.
> +      This is only applicable when the PLL is bypassed.
> +
> +  adi,inverse-sinc-enable:
> +    type: boolean
> +    description:
> +      Enable the inverse sinc filter that compensates for the sinc roll-off
> +      of the DAC output. When it is enabled, the filter introduces up to 3 dB
> +      of insertion loss.
> +
> +  adi,sine-output-enable:
> +    type: boolean
> +    description:
> +      Select sine wave output from the DDS core. When not set, the
> +      output is a cosine wave.

And these last few are really getting into things that are typically
controlled by the IIO driver and not hard-coded.

> +
> +  adi,sync-clk-disable:
> +    type: boolean
> +    description:
> +      Disable the SYNC_CLK output pin. SYNC_CLK runs at one quarter
> +      of the system clock frequency.

Clock outputs should be described as clock-controller and #clock-cells.
The actual enabling/disabling can be done at runtime.

> +
> +  adi,pdclk-disable:
> +    type: boolean
> +    description:
> +      Disable the parallel data clock (PDCLK) output. PDCLK runs at
> +      one quarter of the system clock frequency.
> +
> +  adi,pdclk-invert:
> +    type: boolean
> +    description:
> +      Invert the polarity of the PDCLK output.
> +
> +  adi,tx-enable-invert:
> +    type: boolean
> +    description:
> +      Invert the polarity of the TX_ENABLE input pin.
> +
> +  adi,dac-output-current-microamp:
> +    minimum: 8640
> +    maximum: 31590
> +    default: 20070
> +    description:
> +      DAC full-scale output current in microamps.
> +
> +dependencies:
> +  adi,pll-vco-select: [ 'adi,pll-multiplier' ]
> +  adi,charge-pump-current-microamp: [ 'adi,pll-multiplier' ]
> +  adi,refclk-out-drive-strength: [ 'adi,pll-multiplier' ]
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - dvdd-io33-supply
> +  - avdd33-supply
> +  - dvdd18-supply
> +  - avdd18-supply
> +
> +dependentSchemas:
> +  resets:
> +    properties:
> +      reset-gpios: false
> +  reset-gpios:
> +    properties:
> +      resets: false

This seems too strict. Couldn't we have some resets from a reset
controller and others from gpios?

Or maybe the reset bindings are enough and we don't need the gpio
bindings for the same pin?

> +  adi,reference-div2-enable:
> +    properties:
> +      adi,pll-multiplier: false
> +  adi,pll-multiplier:
> +    properties:
> +      adi,reference-div2-enable: false
> +
> +allOf:
> +  - $ref: /schemas/spi/spi-peripheral-props.yaml#
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +    spi {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +        dds@0 {
> +            compatible = "adi,ad9910";
> +            reg = <0>;
> +            spi-max-frequency = <1000000>;
> +            clocks = <&ad9910_refclk>;
> +
> +            dvdd-io33-supply = <&vdd_io33>;
> +            avdd33-supply = <&vdd_a33>;
> +            dvdd18-supply = <&vdd_d18>;
> +            avdd18-supply = <&vdd_a18>;
> +
> +            reset-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>,
> +                          <&gpio 1 GPIO_ACTIVE_HIGH>;
> +            powerdown-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
> +            update-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
> +            profile-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>,
> +                            <&gpio 5 GPIO_ACTIVE_HIGH>,
> +                            <&gpio 6 GPIO_ACTIVE_HIGH>;
> +
> +            adi,pll-multiplier = <40>;
> +            adi,charge-pump-current-microamp = <387>;
> +            adi,refclk-out-drive-strength = "disabled";
> +            adi,inverse-sinc-enable;
> +        };
> +    };
> +...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1251965d70bd..79b4180e2334 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1610,6 +1610,13 @@ W:	https://ez.analog.com/linux-software-drivers
>  F:	Documentation/devicetree/bindings/iio/dac/adi,ad9739a.yaml
>  F:	drivers/iio/dac/ad9739a.c
>  
> +ANALOG DEVICES INC AD9910 DRIVER
> +M:	Rodrigo Alencar <rodrigo.alencar@analog.com>
> +L:	linux-iio@vger.kernel.org
> +S:	Supported
> +W:	https://ez.analog.com/linux-software-drivers
> +F:	Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> +
>  ANALOG DEVICES INC MAX22007 DRIVER
>  M:	Janani Sunil <janani.sunil@analog.com>
>  L:	linux-iio@vger.kernel.org
>
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Rodrigo Alencar 1 month, 1 week ago
On 26/02/21 02:43PM, David Lechner wrote:
> On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:
> > From: Rodrigo Alencar <rodrigo.alencar@analog.com>

...

> > +  resets:
> > +    minItems: 1
> > +    maxItems: 2
> > +
> > +  reset-names:
> > +    oneOf:
> > +      - items:
> > +          - const: dev
> > +      - items:
> > +          - const: dev
> > +          - const: io
> 
> This could be a bit more clear. Does dev == MASTER_RESET pin?

Correct.

> And what about DAC_RSET?

DAC_RSET is not a reset, it is a pin for a 10K omh resistor.
 
> > +
> > +  reset-gpios:
> > +    maxItems: 2
> > +    description:
> > +      GPIOs controlling the device reset and the I/O_RESET pins. This is only
> > +      used if resets property is not defined.
> > +
> > +  powerdown-gpios:
> > +    maxItems: 1
> > +    description:
> > +      GPIO controlling the EXT_PWR_DWN pin.
> > +
> > +  update-gpios:
> > +    maxItems: 1
> > +    description:
> > +      GPIO controlling the I/O_UPDATE pin.
> > +
> > +  profile-gpios:
> > +    minItems: 3
> > +    maxItems: 3
> > +    description:
> > +      GPIOs controlling the PROFILE[2:0] pins for profile selection.
> > +
> 
> Looks like possibly some interrupts as well: RAM_SWP_OVR and SYNC_SMP_ERR

Interrupts are not handled by the driver at this point, so they were not added
here. The device is meant to have some features exposed through SPI, but to
extract the most of it needs to interface with an FPGA. For that, an IIO
backend is in the works.

> > +  adi,pll-multiplier:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 12
> > +    maximum: 127
> > +    description:
> > +      PLL feedback divider value (N). The system clock frequency is
> > +      REFCLK * N. When not specified, the PLL is bypassed.
> 
> What determines the value that should be selected here? This doesn't seem like
> something we would normally put in the devicetree. (Smells like configuration
> rather than describing what is wired up.)

The sysclk frequency is something we want fixed because it derives the sync_clk
and pd_clk which can be constraints for FPGA desing or when interfacing with
the parallel port (high-speed up to 250 MHz). Also, when using the PLL path to
derive the sysclk, the external loop filter will pretty much define the values
to be used here, as it would be optimized for a certain frequency range.

> > +
> > +  adi,pll-vco-select:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    minimum: 0
> > +    maximum: 5
> > +    description: |
> > +      VCO frequency range selection (0-5). When not specified and the PLL
> > +      is enabled, the VCO range is automatically selected based on the
> > +      computed system clock frequency. Typical VCO frequency ranges are:
> > +      - Range 0: 370 MHz to 510 MHz (Auto-selected when <= 465 MHz)
> > +      - Range 1: 420 MHz to 590 MHz (Auto-selected when > 465 MHz and <= 545 MHz)
> > +      - Range 2: 500 MHz to 700 MHz (Auto-selected when > 545 MHz and <= 650 MHz)
> > +      - Range 3: 600 MHz to 880 MHz (Auto-selected when > 650 MHz and <= 790 MHz)
> > +      - Range 4: 700 MHz to 950 MHz (Auto-selected when > 790 MHz and <= 885 MHz)
> > +      - Range 5: 820 MHz to 1050 MHz (Auto-selected when > 885 MHz)
> > +
> 
> Same here. How does this depend on how the chip is wired up?

That applies to when the PLL path is used. FPGA interface and loop filter design.
I can write those details as part of the description.

> > +  adi,charge-pump-current-microamp:
> > +    minimum: 212
> > +    maximum: 387
> > +    default: 387
> > +    description:
> > +      PLL charge pump current in microamps. Only applicable when the PLL
> > +      is enabled. The value is rounded to the nearest supported step.
> > +
> > +  adi,refclk-out-drive-strength:
> > +    $ref: /schemas/types.yaml#/definitions/string
> > +    enum: [ disabled, low, medium, high ]
> > +    default: disabled
> > +    description:
> > +      Reference clock output (DRV0) drive strength. Only applicable when
> > +      the PLL is enabled.
> > +
> > +  adi,reference-div2-enable:
> > +    type: boolean
> > +    description:
> > +      Enable the reference clock input divider. When enabled, the input
> > +      reference frequency is halved before deriving the system clock.
> > +      This is only applicable when the PLL is bypassed.
> > +
> > +  adi,inverse-sinc-enable:
> > +    type: boolean
> > +    description:
> > +      Enable the inverse sinc filter that compensates for the sinc roll-off
> > +      of the DAC output. When it is enabled, the filter introduces up to 3 dB
> > +      of insertion loss.
> > +
> > +  adi,sine-output-enable:
> > +    type: boolean
> > +    description:
> > +      Select sine wave output from the DDS core. When not set, the
> > +      output is a cosine wave.
> 
> And these last few are really getting into things that are typically
> controlled by the IIO driver and not hard-coded.

indeed, adi,sine-output-enable could be removed from here.

> > +
> > +  adi,sync-clk-disable:
> > +    type: boolean
> > +    description:
> > +      Disable the SYNC_CLK output pin. SYNC_CLK runs at one quarter
> > +      of the system clock frequency.
> 
> Clock outputs should be described as clock-controller and #clock-cells.
> The actual enabling/disabling can be done at runtime.

I thought of that, but when interfacing with an FPGA, the clock consumer
will be the IIO backend itself, which this device driver would depend on.
It would create a cyclic dependency during the probe of the drivers:
- This device being a clock provider and an IIO backend consumer
- The FPGA IP being a IIO backend provider and a clock consumer.

This would be just save some power when not interfacing with an FPGA,
there would not be a clock consumer to get the clock disabled.
Normally, clock consumers would want to have clock enabled, which is
already the case by default.

I would add the FPGA/IIO backend support in a separate patch series,
as it would bring more stuff here.

> > +
> > +  adi,pdclk-disable:
> > +    type: boolean
> > +    description:
> > +      Disable the parallel data clock (PDCLK) output. PDCLK runs at
> > +      one quarter of the system clock frequency.
> > +
> > +  adi,pdclk-invert:
> > +    type: boolean
> > +    description:
> > +      Invert the polarity of the PDCLK output.
> > +
> > +  adi,tx-enable-invert:
> > +    type: boolean
> > +    description:
> > +      Invert the polarity of the TX_ENABLE input pin.
> > +
> > +  adi,dac-output-current-microamp:
> > +    minimum: 8640
> > +    maximum: 31590
> > +    default: 20070
> > +    description:
> > +      DAC full-scale output current in microamps.
> > +
> > +dependencies:
> > +  adi,pll-vco-select: [ 'adi,pll-multiplier' ]
> > +  adi,charge-pump-current-microamp: [ 'adi,pll-multiplier' ]
> > +  adi,refclk-out-drive-strength: [ 'adi,pll-multiplier' ]
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - dvdd-io33-supply
> > +  - avdd33-supply
> > +  - dvdd18-supply
> > +  - avdd18-supply
> > +
> > +dependentSchemas:
> > +  resets:
> > +    properties:
> > +      reset-gpios: false
> > +  reset-gpios:
> > +    properties:
> > +      resets: false
> 
> This seems too strict. Couldn't we have some resets from a reset
> controller and others from gpios?

I suppose that would be confusing. using reset-gpios is the case where
we are NOT interfacing with an FPGA. Otherwise, using resets would be the
case when the IIO backend also implements the reset controller interface.

> Or maybe the reset bindings are enough and we don't need the gpio
> bindings for the same pin?

normally reset-gpios are enough as it can be used to instantiate a
reset controller too. I could introduce resets when adding the IIO backend
support.

-- 
Kind regards,

Rodrigo Alencar
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Conor Dooley 1 month, 1 week ago
On Sun, Feb 22, 2026 at 10:47:41AM +0000, Rodrigo Alencar wrote:
> On 26/02/21 02:43PM, David Lechner wrote:
> > On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:
> > > From: Rodrigo Alencar <rodrigo.alencar@analog.com>

> > > +
> > > +  reset-gpios:
> > > +    maxItems: 2
> > > +    description:
> > > +      GPIOs controlling the device reset and the I/O_RESET pins. This is only
> > > +      used if resets property is not defined.
> > > +
> > > +  powerdown-gpios:
> > > +    maxItems: 1
> > > +    description:
> > > +      GPIO controlling the EXT_PWR_DWN pin.
> > > +
> > > +  update-gpios:
> > > +    maxItems: 1
> > > +    description:
> > > +      GPIO controlling the I/O_UPDATE pin.
> > > +
> > > +  profile-gpios:
> > > +    minItems: 3
> > > +    maxItems: 3
> > > +    description:
> > > +      GPIOs controlling the PROFILE[2:0] pins for profile selection.
> > > +
> > 
> > Looks like possibly some interrupts as well: RAM_SWP_OVR and SYNC_SMP_ERR
> 
> Interrupts are not handled by the driver at this point, so they were not added
> here. The device is meant to have some features exposed through SPI, but to
> extract the most of it needs to interface with an FPGA. For that, an IIO
> backend is in the works.

The binding should be complete, if there are interrupts then document
them even if the driver doesn't use them. If this is where you say you
mentioned the io-backends, that's not what I meant - you need to do it
in the patch itself to explain why you have the odd setup with resets
and reset-gpios.
That said, if you don't know what the io-backends stuff is going to look
like for this device, you should probably exclude those resets until the
design for the io-backend IP is complete. reset-gpios are usually
optional anyway (since they are often just wired high/low), so there
shouldn't be any downside there.

> > > +  adi,pll-multiplier:
> > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > +    minimum: 12
> > > +    maximum: 127
> > > +    description:
> > > +      PLL feedback divider value (N). The system clock frequency is
> > > +      REFCLK * N. When not specified, the PLL is bypassed.
> > 
> > What determines the value that should be selected here? This doesn't seem like
> > something we would normally put in the devicetree. (Smells like configuration
> > rather than describing what is wired up.)
> 
> The sysclk frequency is something we want fixed because it derives the sync_clk
> and pd_clk which can be constraints for FPGA desing or when interfacing with

btw, the datasheet for this device (rev e) says:
| SYNC_CLK is a rising edge active signal. It is derived from the
| system clock and a divide-by-4 frequency divider. SYNC_CLK,
| which is externally provided, can be used to synchronize external
| hardware to the AD9910 internal clocks.

It's not externally provided, so the third sentence here is confusing.

> the parallel port (high-speed up to 250 MHz). Also, when using the PLL path to
> derive the sysclk, the external loop filter will pretty much define the values
> to be used here, as it would be optimized for a certain frequency range.
> 
> > > +
> > > +  adi,pll-vco-select:
> > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > +    minimum: 0
> > > +    maximum: 5
> > > +    description: |
> > > +      VCO frequency range selection (0-5). When not specified and the PLL
> > > +      is enabled, the VCO range is automatically selected based on the
> > > +      computed system clock frequency. Typical VCO frequency ranges are:
> > > +      - Range 0: 370 MHz to 510 MHz (Auto-selected when <= 465 MHz)
> > > +      - Range 1: 420 MHz to 590 MHz (Auto-selected when > 465 MHz and <= 545 MHz)
> > > +      - Range 2: 500 MHz to 700 MHz (Auto-selected when > 545 MHz and <= 650 MHz)
> > > +      - Range 3: 600 MHz to 880 MHz (Auto-selected when > 650 MHz and <= 790 MHz)
> > > +      - Range 4: 700 MHz to 950 MHz (Auto-selected when > 790 MHz and <= 885 MHz)
> > > +      - Range 5: 820 MHz to 1050 MHz (Auto-selected when > 885 MHz)
> > > +
> > 
> > Same here. How does this depend on how the chip is wired up?
> 
> That applies to when the PLL path is used. FPGA interface and loop filter design.
> I can write those details as part of the description.

This property definitely needs justification given that it looks like
the device will just do the right thing without the property.

> > > +
> > > +  adi,sync-clk-disable:
> > > +    type: boolean
> > > +    description:
> > > +      Disable the SYNC_CLK output pin. SYNC_CLK runs at one quarter
> > > +      of the system clock frequency.
> > 
> > Clock outputs should be described as clock-controller and #clock-cells.
> > The actual enabling/disabling can be done at runtime.
> 
> I thought of that, but when interfacing with an FPGA, the clock consumer
> will be the IIO backend itself, which this device driver would depend on.
> It would create a cyclic dependency during the probe of the drivers:
> - This device being a clock provider and an IIO backend consumer
> - The FPGA IP being a IIO backend provider and a clock consumer.
> 
> This would be just save some power when not interfacing with an FPGA,
> there would not be a clock consumer to get the clock disabled.
> Normally, clock consumers would want to have clock enabled, which is
> already the case by default.
> 
> I would add the FPGA/IIO backend support in a separate patch series,
> as it would bring more stuff here.

Honestly, this binding design seems so tightly integrated with the
io-backend that you're shooting yourself in the foot, and making it hard
for us to review, by not including it. I think this really should be a
clock provider and the io-backend a clock consumer, even if it causes a
cyclical dependency. One of the two can probably be a post-init-provider
to the other, probably something like sync_clk doesn't need to be set at
probe, and setting the rate can be delayed until we start needing data
from the device? Since both sync_clk and pdclk are provided by the
ad9910 to the io-backend, your driver will have control over what the
rates of these clocks are and you shouldn't need to hard code the
multipliers etc. You just need to know if the parallel bus is in use or
not. I'm not sure if that's a given if there's an io-backend and you're
not on a serial bus or if would need a property to identify.

Most of the clocking related properties here seem like they go away if
you make the device a clock-controller, for example the driver should be
able to decide if the needs to enable reference-div2 to achieve the
internal frequencies that it needs. sync-clk-disable would be done
automatically if there's no consumer of sync_clk etc.

Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by David Lechner 1 month, 1 week ago
On 2/22/26 4:47 AM, Rodrigo Alencar wrote:
> On 26/02/21 02:43PM, David Lechner wrote:
>> On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:
>>> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
> 

...

>>> +
>>> +  reset-gpios:
>>> +    maxItems: 2
>>> +    description:
>>> +      GPIOs controlling the device reset and the I/O_RESET pins. This is only
>>> +      used if resets property is not defined.
>>> +
>>> +  powerdown-gpios:
>>> +    maxItems: 1
>>> +    description:
>>> +      GPIO controlling the EXT_PWR_DWN pin.
>>> +
>>> +  update-gpios:
>>> +    maxItems: 1
>>> +    description:
>>> +      GPIO controlling the I/O_UPDATE pin.
>>> +
>>> +  profile-gpios:
>>> +    minItems: 3
>>> +    maxItems: 3
>>> +    description:
>>> +      GPIOs controlling the PROFILE[2:0] pins for profile selection.
>>> +
>>
>> Looks like possibly some interrupts as well: RAM_SWP_OVR and SYNC_SMP_ERR
> 
> Interrupts are not handled by the driver at this point, so they were not added
> here. The device is meant to have some features exposed through SPI, but to
> extract the most of it needs to interface with an FPGA. For that, an IIO
> backend is in the works.


DT bindings should aim to be complete. It doesn't matter what the driver
implements or not.

We make exceptions for things that haven't been seen before where the
bindings might not be obvious, but output pins like this (at least the
error one) are pretty much always connected to interrupts.

Also, the interrupt properties should not be required. So if the output
line is connected to an io-backend instead of an interrupt, that is fine.
The bindings should cover all ways this could possibly be wired up.



>>> +
>>> +  adi,sync-clk-disable:
>>> +    type: boolean
>>> +    description:
>>> +      Disable the SYNC_CLK output pin. SYNC_CLK runs at one quarter
>>> +      of the system clock frequency.
>>
>> Clock outputs should be described as clock-controller and #clock-cells.
>> The actual enabling/disabling can be done at runtime.
> 
> I thought of that, but when interfacing with an FPGA, the clock consumer
> will be the IIO backend itself, which this device driver would depend on.
> It would create a cyclic dependency during the probe of the drivers:
> - This device being a clock provider and an IIO backend consumer
> - The FPGA IP being a IIO backend provider and a clock consumer.

As above, the binding should not depend on what the driver does. There is
a standard binding for this, so we should use it. I'm sure we could find
a way to make it work in the driver even if it is just manually parsing the
properties instead of going through the clock framework. I.e. if the
clock-controller property is present, turn on the clock output, otherwise
turn off the clock output.

> 
> This would be just save some power when not interfacing with an FPGA,
> there would not be a clock consumer to get the clock disabled.
> Normally, clock consumers would want to have clock enabled, which is
> already the case by default.
> 
> I would add the FPGA/IIO backend support in a separate patch series,
> as it would bring more stuff here.
>
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Conor Dooley 1 month, 1 week ago
On Sat, Feb 21, 2026 at 02:43:02PM -0600, David Lechner wrote:
> On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:

> > +dependentSchemas:
> > +  resets:
> > +    properties:
> > +      reset-gpios: false
> > +  reset-gpios:
> > +    properties:
> > +      resets: false
> 
> This seems too strict. Couldn't we have some resets from a reset
> controller and others from gpios?
> 
> Or maybe the reset bindings are enough and we don't need the gpio
> bindings for the same pin?

Actually, I'd be interested in seeing evidence for the resets property
ever being used with this device. I think every single reset-controller
that's currently documented is an on-chip device for resetting
peripherals.
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Rodrigo Alencar 1 month, 1 week ago
On 26/02/21 10:43PM, Conor Dooley wrote:
> On Sat, Feb 21, 2026 at 02:43:02PM -0600, David Lechner wrote:
> > On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:
> 
> > > +dependentSchemas:
> > > +  resets:
> > > +    properties:
> > > +      reset-gpios: false
> > > +  reset-gpios:
> > > +    properties:
> > > +      resets: false
> > 
> > This seems too strict. Couldn't we have some resets from a reset
> > controller and others from gpios?
> > 
> > Or maybe the reset bindings are enough and we don't need the gpio
> > bindings for the same pin?
> 
> Actually, I'd be interested in seeing evidence for the resets property
> ever being used with this device. I think every single reset-controller
> that's currently documented is an on-chip device for resetting
> peripherals.

As mentioned, an FPGA IP as an IIO backend (MMIO platform_device) will
implement the reset controller interface.

-- 
Kind regards,

Rodrigo Alencar
Re: [PATCH RFC 1/8] dt-bindings: iio: frequency: add ad9910
Posted by Conor Dooley 1 month, 1 week ago
On Sun, Feb 22, 2026 at 10:49:35AM +0000, Rodrigo Alencar wrote:
> On 26/02/21 10:43PM, Conor Dooley wrote:
> > On Sat, Feb 21, 2026 at 02:43:02PM -0600, David Lechner wrote:
> > > On 2/20/26 10:46 AM, Rodrigo Alencar via B4 Relay wrote:
> > 
> > > > +dependentSchemas:
> > > > +  resets:
> > > > +    properties:
> > > > +      reset-gpios: false
> > > > +  reset-gpios:
> > > > +    properties:
> > > > +      resets: false
> > > 
> > > This seems too strict. Couldn't we have some resets from a reset
> > > controller and others from gpios?
> > > 
> > > Or maybe the reset bindings are enough and we don't need the gpio
> > > bindings for the same pin?
> > 
> > Actually, I'd be interested in seeing evidence for the resets property
> > ever being used with this device. I think every single reset-controller
> > that's currently documented is an on-chip device for resetting
> > peripherals.
> 
> As mentioned, an FPGA IP as an IIO backend (MMIO platform_device) will
> implement the reset controller interface.

I think you're confusing this with some other patch, I don't see any
mention of FPGA IPs or io-backends here.