From 9ceb2b2bfcf594238af7eca28bf64877de128c89 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 16:03:50 -0300 Subject: [PATCH 01/75] ARM: dts: xilinx: Fix clock controller node conflict The clock controller node name conflicts with the DMA clock controller instance in the zynq-zed-adv7511.dtsi file and causes a device probe error. To solve that, prepend application specific info to clock controller node names. Fixes: f3fdbc8f355f ("arch: dts: rename adi,axi-clkgen-2.00.a nodes to clock-controller") Co-developed-by: Jonathan Santos Signed-off-by: Jonathan Santos Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad3552r-hs.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4000.dtsi | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4030-24.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4032-24.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-16.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-24.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4696.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7625.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7960.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4216.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4220.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24.dts | 2 +- .../dts/xilinx/zynq-zed-adv7511-adaq4224-24_cm0_sdi4_cz2.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ltc2387.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-m2k-revb.dts | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad3552r-hs.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad3552r-hs.dts index f77f4cf1ccc6d6..92f816ccc7b190 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad3552r-hs.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad3552r-hs.dts @@ -50,7 +50,7 @@ }; &fpga_axi { - ref_clk: clock-controller@44B00000 { + ref_clk: spi-clock-controller@44B00000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44B00000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4000.dtsi b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4000.dtsi index 5c6e341d340780..8bc40b83301121 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4000.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4000.dtsi @@ -94,7 +94,7 @@ clocks = <&clkc 17>; }; - spi_clk: clock-controller@0x44a70000 { + spi_clk: spi-clock-controller@0x44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4030-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4030-24.dts index c70017f98fde00..59165fdb9b3a7b 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4030-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4030-24.dts @@ -58,7 +58,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4032-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4032-24.dts index fc1ed92fe352db..144f48f6d097a4 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4032-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4032-24.dts @@ -58,7 +58,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index 8bb11765d3076a..429bcfca0d9d57 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -95,7 +95,7 @@ clock-names = "axi", "ext"; }; - spi_clk: clock-controller@44b10000 { + spi_clk: spi-clock-controller@44b10000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44b10000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-16.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-16.dts index e9d4f05f0ab6e7..ed523d44daefe6 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-16.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-16.dts @@ -58,7 +58,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-24.dts index 8a883184f982e0..dc5ec464cf185a 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4630-24.dts @@ -72,7 +72,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4696.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4696.dts index 733e469e820a9b..7f98f78df446f8 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4696.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4696.dts @@ -74,7 +74,7 @@ clock-names = "axi", "ext"; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7625.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7625.dts index 3296844e6a27c5..2f0b90c916523d 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7625.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7625.dts @@ -67,7 +67,7 @@ clocks = <&clkc 15>; }; - ref_clk: clock-controller@44a80000 { + ref_clk: spi-clock-controller@44a80000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a80000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7960.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7960.dts index f77ff83b6c86ab..fc78c0c01a8cc8 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7960.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7960.dts @@ -69,7 +69,7 @@ clocks = <&clkc 15>; }; - ref_clk: clock-controller@44a80000 { + ref_clk: spi-clock-controller@44a80000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a80000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4216.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4216.dts index 734c61d899d2f7..c0bced262a4f19 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4216.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4216.dts @@ -74,7 +74,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4220.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4220.dts index cc71b571b30c70..af311f52129c88 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4220.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4220.dts @@ -85,7 +85,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24.dts index 847d7872b8804e..981645ef5ae0db 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24.dts @@ -85,7 +85,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24_cm0_sdi4_cz2.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24_cm0_sdi4_cz2.dts index 35a0ae473d4e1d..cf6b47fa86fc5d 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24_cm0_sdi4_cz2.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-adaq4224-24_cm0_sdi4_cz2.dts @@ -72,7 +72,7 @@ clocks = <&clkc 15>; }; - spi_clk: clock-controller@44a70000 { + spi_clk: spi-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ltc2387.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ltc2387.dts index d3859eb41fdc1c..e74edbda6be3b3 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ltc2387.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ltc2387.dts @@ -34,7 +34,7 @@ clocks = <&clkc 15>; }; - ref_clk: clock-controller@44a70000 { + ref_clk: ref-clock-controller@44a70000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x44a70000 0x10000>; #clock-cells = <0>; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-m2k-revb.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-m2k-revb.dts index f0654ea295ba42..1845a3e5abb572 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-m2k-revb.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-m2k-revb.dts @@ -200,7 +200,7 @@ adi,axi-dds-default-frequency = <1000000>; }; - logic_analyzer_clkgen: clock-controller@7000000 { + logic_analyzer_clkgen: m2k-clock-controller@7000000 { compatible = "adi,axi-clkgen-2.00.a"; reg = <0x70000000 0x10000>; clocks = <&clkc 16>, <&clkc 15>; From 856390c2aaeebd87a3a829cc4c8657d4701b06f6 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 2 Jul 2024 11:22:02 -0300 Subject: [PATCH 02/75] dt-bindings: iio: adc: adi,ad4134: Add adi,adc-frame property Add device tree property to configure ADC data packet size so drivers can properly configure data channels. Signed-off-by: Marcelo Schmitt --- .../devicetree/bindings/iio/adc/adi,ad4134.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml index 96feca8fb42b8d..949bf61b3b7bd2 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml @@ -56,6 +56,15 @@ properties: iovdd-supply: true refin-supply: true + adi,adc-frame: + $ref: /schemas/types.yaml#/definitions/string + enum: [ 16-bit, 16-bit+CRC, 24-bit, 24-bit+CRC ] + default: 24-bit + description: + Describes how the ADC data packet should be configured. The data packet + size is 16-bit when "16-bit" is selected, 24-bit when "16-bit+CRC" or + "24-bit" are selected, and 32-bit when "24-bit+CRC" is set. + adi,spi-engine: $ref: /schemas/types.yaml#/definitions/phandle description: phandle of the SPI slave connected to the SPI engine master @@ -104,6 +113,7 @@ examples: iovdd-supply = <&iovdd>; refin-supply = <&refin>; + adi,adc-frame = "24-bit"; adi,spi-engine = <&ad4134_spi_engine>; }; }; From 48e6ce09da3d9ad46b4e5f1bb113e83545aee95a Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 2 Jul 2024 15:43:40 -0300 Subject: [PATCH 03/75] dt-bindings: iio: adc: adi,ad4134: Add cs-gpios property In projects that contain two ADCs, the synchronization procedure requires a synchronization signal sent to both ADCs. The cs-gpio is used to provide that synchronization signal. Signed-off-by: Marcelo Schmitt --- Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml index 949bf61b3b7bd2..4b13c3561db6ad 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml @@ -30,6 +30,12 @@ properties: reset-gpios: maxItems: 1 + cs-gpios: + description: + Used to synchronize devices when two or more ADCs are used for + synchronized data sampling. + maxItems: 1 + clocks: maxItems: 1 From 51dc556ad28cbd6ef8568d26d6fd3f53a4994924 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 2 Jul 2024 12:00:01 -0300 Subject: [PATCH 04/75] dt-bindings: iio: adc: adi,ad4134: Add compatible for AD7134 Signed-off-by: Marcelo Schmitt --- Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml index 4b13c3561db6ad..52efd1852bf075 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml @@ -18,8 +18,12 @@ description: | properties: compatible: - enum: - - adi,ad4134 + oneOf: + - const: adi,ad4134 + - items: + - enum: + - adi,ad7134 + - const: adi,ad4134 reg: maxItems: 1 From 4ff04d06eb86d2a47aeb8144a269143922d28c81 Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 17:36:22 -0300 Subject: [PATCH 05/75] iio: adc: ad4134: Add missing include for error macros Include header file for error macros used in the AD4134 driver. Fixes: 5d5bac73e12d ("iio: adc: ad4134: add AD4134 driver") Signed-off-by: Ioan-daniel Pop Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 72a008b2ca309c..e574a2e418036e 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include From 9bde84f27b82ed6a15b359059312b2fc62ad47d2 Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 16:46:14 -0300 Subject: [PATCH 06/75] iio: adc: ad4134: Add support for ADC output frame config The AD4134 and AD7134 support four different data packet frame configurations: * 16-bit ADC data, * 16-bit ADC data followed by 6 CRC bits, * 24-bit ADC data, * 24-bit ADC data followed by 6 CRC bits. Each configuration leads to a slightly different need of real data bits, storage bits, or data shift. Construct and provide proper IIO channels according to the data frame device tree property. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 115 +++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 36 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index e574a2e418036e..8a7f59a059987c 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -32,7 +32,10 @@ #define AD4134_DATA_PACKET_CONFIG_REG 0x11 #define AD4134_DATA_PACKET_CONFIG_FRAME_MASK GENMASK(5, 4) -#define AD4134_DATA_FRAME_24BIT_CRC 0b11 +#define AD4134_DATA_PACKET_16BIT_FRAME 0x0 +#define AD4134_DATA_PACKET_16BIT_CRC6_FRAME 0x1 +#define AD4134_DATA_PACKET_24BIT_FRAME 0x2 +#define AD4134_DATA_PACKET_24BIT_CRC6_FRAME 0x3 #define AD4134_DIG_IF_CFG_REG 0x12 #define AD4134_DIF_IF_CFG_FORMAT_MASK GENMASK(1, 0) @@ -42,10 +45,6 @@ #define AD4134_ODR_MAX 1496000 #define AD4134_ODR_DEFAULT 300000 -#define AD4134_NUM_CHANNELS 4 -#define AD4134_REAL_BITS 24 -#define AD4134_WORD_BITS 32 - #define AD4134_RESET_TIME_US 10000000 enum ad4134_regulators { @@ -56,6 +55,47 @@ enum ad4134_regulators { AD4134_NUM_REGULATORS }; +/* maps adi,adc-frame property value to enum */ +static const char * const ad4134_frame_config[] = { + [AD4134_DATA_PACKET_16BIT_FRAME] = "16-bit", + [AD4134_DATA_PACKET_16BIT_CRC6_FRAME] = "16-bit+CRC", + [AD4134_DATA_PACKET_24BIT_FRAME] = "24-bit", + [AD4134_DATA_PACKET_24BIT_CRC6_FRAME] = "24-bit+CRC", +}; + +#define AD4134_CHANNEL(_index, _realbits, _storebits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = (_index), \ + .scan_type = { \ + .sign = 's', \ + .realbits = (_realbits), \ + .storagebits = (_storebits), \ + .shift = ((_storebits) - (_realbits)) \ + }, \ +} + +#define AD4134_CHAN_SET(_realbits, _storebits) { \ + AD4134_CHANNEL(0, _realbits, _storebits), \ + AD4134_CHANNEL(1, _realbits, _storebits), \ + AD4134_CHANNEL(2, _realbits, _storebits), \ + AD4134_CHANNEL(3, _realbits, _storebits), \ +} + +static const struct iio_chan_spec ad4134_16_chan_set[] = AD4134_CHAN_SET(16, 16); +static const struct iio_chan_spec ad4134_16CRC_chan_set[] = AD4134_CHAN_SET(16, 24); +static const struct iio_chan_spec ad4134_24_chan_set[] = AD4134_CHAN_SET(24, 24); +static const struct iio_chan_spec ad4134_24CRC_chan_set[] = AD4134_CHAN_SET(24, 32); + +static const unsigned long ad4134_channel_masks[] = { + GENMASK(ARRAY_SIZE(ad4134_16_chan_set) - 1, 0), + 0, +}; + struct ad4134_state { struct fwnode_handle *spi_engine_fwnode; struct regmap *regmap; @@ -76,6 +116,7 @@ struct ad4134_state { unsigned int odr; unsigned long sys_clk_rate; int refin_mv; + int output_frame; }; static int ad4134_samp_freq_avail[] = { AD4134_ODR_MIN, 1, AD4134_ODR_MAX }; @@ -197,35 +238,6 @@ static const struct iio_info ad4134_info = { .debugfs_reg_access = ad4134_reg_access, }; -#define AD4134_CHANNEL(index) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = (index), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ - BIT(IIO_CHAN_INFO_SCALE), \ - .info_mask_shared_by_type_available = \ - BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .scan_index = (index), \ - .scan_type = { \ - .sign = 's', \ - .realbits = AD4134_REAL_BITS, \ - .storagebits = 32, \ - .shift = AD4134_WORD_BITS - AD4134_REAL_BITS \ - }, \ -} - -static const struct iio_chan_spec ad4134_channels[] = { - AD4134_CHANNEL(0), - AD4134_CHANNEL(1), - AD4134_CHANNEL(2), - AD4134_CHANNEL(3), -}; - -static const unsigned long ad4134_channel_masks[] = { - GENMASK(AD4134_NUM_CHANNELS - 1, 0), - 0, -}; - static int ad4134_buffer_postenable(struct iio_dev *indio_dev) { struct ad4134_state *st = iio_priv(indio_dev); @@ -331,7 +343,7 @@ static int ad4134_setup(struct ad4134_state *st) ret = regmap_update_bits(st->regmap, AD4134_DATA_PACKET_CONFIG_REG, AD4134_DATA_PACKET_CONFIG_FRAME_MASK, FIELD_PREP(AD4134_DATA_PACKET_CONFIG_FRAME_MASK, - AD4134_DATA_FRAME_24BIT_CRC)); + st->output_frame)); if (ret) return ret; @@ -419,13 +431,44 @@ static int ad4134_probe(struct spi_device *spi) st->regulators[AD4134_IOVDD_REGULATOR].supply = "iovdd"; st->regulators[AD4134_REFIN_REGULATOR].supply = "refin"; + st->output_frame = AD4134_DATA_PACKET_24BIT_FRAME; + ret = device_property_match_property_string(dev, "adi,adc-frame", + ad4134_frame_config, + ARRAY_SIZE(ad4134_frame_config)); + if (ret < 0) + dev_warn(dev, "Failed to get adi,adc-frame property: %d\n", ret); + else + st->output_frame = ret; + + switch (st->output_frame) { + case AD4134_DATA_PACKET_16BIT_FRAME: + indio_dev->channels = ad4134_16_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_16_chan_set); + break; + case AD4134_DATA_PACKET_16BIT_CRC6_FRAME: + indio_dev->channels = ad4134_16CRC_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_16CRC_chan_set); + break; + case AD4134_DATA_PACKET_24BIT_FRAME: + indio_dev->channels = ad4134_24_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_24_chan_set); + break; + case AD4134_DATA_PACKET_24BIT_CRC6_FRAME: + indio_dev->channels = ad4134_24CRC_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_24CRC_chan_set); + break; + default: + return dev_err_probe(dev, -EINVAL, + "Failed to config ADC frame\n"); + } + /* * Receive buffer needs to be non-zero for the SPI engine master * to mark the transfer as a read. */ st->buf_read_xfer.rx_buf = (void *)-1; st->buf_read_xfer.len = 1; - st->buf_read_xfer.bits_per_word = AD4134_WORD_BITS; + st->buf_read_xfer.bits_per_word = indio_dev->channels->scan_type.storagebits; spi_message_init_with_transfers(&st->buf_read_msg, &st->buf_read_xfer, 1); From 85c75128f9c41f35722e88961764269c66ff1bc4 Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 17:10:33 -0300 Subject: [PATCH 07/75] iio: adc: ad4134: Add iio_chan_spec_ext_info for the ODR Add channel extended info for the ODR (Output Data Rate) signal. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 88 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 8a7f59a059987c..e11b3a6ec7ac3a 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -43,10 +43,14 @@ #define AD4134_ODR_MIN 10 #define AD4134_ODR_MAX 1496000 -#define AD4134_ODR_DEFAULT 300000 +#define AD4134_ODR_DEFAULT 1496000 #define AD4134_RESET_TIME_US 10000000 +enum { + ODR_SET_FREQ, +}; + enum ad4134_regulators { AD4134_AVDD5_REGULATOR, AD4134_AVDD1V8_REGULATOR, @@ -63,7 +67,7 @@ static const char * const ad4134_frame_config[] = { [AD4134_DATA_PACKET_24BIT_CRC6_FRAME] = "24-bit+CRC", }; -#define AD4134_CHANNEL(_index, _realbits, _storebits) { \ +#define AD4134_CHANNEL(_index, _realbits, _storebits, _ext_info) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = (_index), \ @@ -77,13 +81,33 @@ static const char * const ad4134_frame_config[] = { .storagebits = (_storebits), \ .shift = ((_storebits) - (_realbits)) \ }, \ + .ext_info = _ext_info, \ } +static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len); +static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, char *buf); + +static struct iio_chan_spec_ext_info ad7134_ext_info[] = { + { + .name = "odr_set_freq", + .read = ad7134_ext_info_read, + .write = ad7134_ext_info_write, + .shared = IIO_SHARED_BY_ALL, + .private = ODR_SET_FREQ, + }, + { }, +}; + #define AD4134_CHAN_SET(_realbits, _storebits) { \ - AD4134_CHANNEL(0, _realbits, _storebits), \ - AD4134_CHANNEL(1, _realbits, _storebits), \ - AD4134_CHANNEL(2, _realbits, _storebits), \ - AD4134_CHANNEL(3, _realbits, _storebits), \ + AD4134_CHANNEL(0, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(1, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(2, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(3, _realbits, _storebits, ad7134_ext_info), \ } static const struct iio_chan_spec ad4134_16_chan_set[] = AD4134_CHAN_SET(16, 16); @@ -119,6 +143,29 @@ struct ad4134_state { int output_frame; }; +static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, char *buf) +{ + int ret = -EINVAL; + long long val; + struct ad4134_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + + switch (private) { + case ODR_SET_FREQ: + val = st->odr; + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&st->lock); + + return sprintf(buf, "%lld\n", val); +} + static int ad4134_samp_freq_avail[] = { AD4134_ODR_MIN, 1, AD4134_ODR_MAX }; static int _ad4134_set_odr(struct ad4134_state *st, unsigned int odr) @@ -169,6 +216,35 @@ static int ad4134_set_odr(struct iio_dev *indio_dev, unsigned int odr) return ret; } +static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + int ret = -EINVAL; + long long readin; + struct ad4134_state *st = iio_priv(indio_dev); + + mutex_lock(&st->lock); + + switch (private) { + case ODR_SET_FREQ: + ret = kstrtoll(buf, 10, &readin); + if (ret) + goto out; + readin = clamp_t(long long, readin, 0, 1500000); + ret = _ad4134_set_odr(st, readin); + break; + + default: + ret = -EINVAL; + } +out: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + static int ad4134_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) From a96ecd3d1e6403284d894f40da748bd64ab0536a Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 18:00:00 -0300 Subject: [PATCH 08/75] iio: adc: ad4134: Add support for cs-gpio synchronization signal In projects that contain two ADCs, the synchronization procedure requires a synchronization signal sent to both ADCs. The cs-gpio is used to provide that synchronization signal. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index e11b3a6ec7ac3a..68e6da27cfe4f7 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -136,6 +136,7 @@ struct ad4134_state { struct spi_message buf_read_msg; struct spi_transfer buf_read_xfer; + struct gpio_desc *cs_gpio; unsigned int odr; unsigned long sys_clk_rate; @@ -394,6 +395,11 @@ static int ad4134_setup(struct ad4134_state *st) return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to find reset GPIO\n"); + st->cs_gpio = devm_gpiod_get_optional(dev, "cs", GPIOD_OUT_LOW); + if (IS_ERR(st->cs_gpio)) + return dev_err_probe(dev, PTR_ERR(st->cs_gpio), + "Failed to find cs-gpio\n"); + fsleep(AD4134_RESET_TIME_US); gpiod_set_value_cansleep(reset_gpio, 0); From 25e57457e2d13e1bc869f7dc2a23453205982341 Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 17:53:28 -0300 Subject: [PATCH 09/75] iio: adc: ad4134: Add support for channel digital filter config Signed-off-by: Ioan-daniel Pop Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 90 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 68e6da27cfe4f7..b5d4e24d529cdb 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -41,6 +41,15 @@ #define AD4134_DIF_IF_CFG_FORMAT_MASK GENMASK(1, 0) #define AD4134_DATA_FORMAT_QUAD_CH_PARALLEL 0b10 +#define AD4134_CHAN_DIG_FILTER_SEL_REG 0x1E +#define AD4134_CHAN_DIG_FILTER_SEL_MASK GENMASK(7, 0) +#define AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH0 GENMASK(1, 0) +#define AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH1 GENMASK(3, 2) +#define AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH2 GENMASK(5, 4) +#define AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH3 GENMASK(7, 6) + +#define AD4134_SINC6_FILTER 0b01010101 + #define AD4134_ODR_MIN 10 #define AD4134_ODR_MAX 1496000 #define AD4134_ODR_DEFAULT 1496000 @@ -67,6 +76,20 @@ static const char * const ad4134_frame_config[] = { [AD4134_DATA_PACKET_24BIT_CRC6_FRAME] = "24-bit+CRC", }; +enum ad7134_flt_type { + WIDEBAND, + SINC6, + SINC3, + SINC3_REJECTION +}; + +static const char * const ad7134_filter_enum[] = { + [WIDEBAND] = "WIDEBAND", + [SINC6] = "SINC6", + [SINC3] = "SINC3", + [SINC3_REJECTION] = "SINC3_REJECTION", +}; + #define AD4134_CHANNEL(_index, _realbits, _storebits, _ext_info) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -84,6 +107,11 @@ static const char * const ad4134_frame_config[] = { .ext_info = _ext_info, \ } +static int ad7134_set_dig_fil(struct iio_dev *dev, + const struct iio_chan_spec *chan, + unsigned int filter); +static int ad7134_get_dig_fil(struct iio_dev *dev, + const struct iio_chan_spec *chan); static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, @@ -92,7 +120,16 @@ static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, char *buf); +static const struct iio_enum ad7134_flt_type_iio_enum = { + .items = ad7134_filter_enum, + .num_items = ARRAY_SIZE(ad7134_filter_enum), + .set = ad7134_set_dig_fil, + .get = ad7134_get_dig_fil, +}; + static struct iio_chan_spec_ext_info ad7134_ext_info[] = { + IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7134_flt_type_iio_enum), + IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL, &ad7134_flt_type_iio_enum), { .name = "odr_set_freq", .read = ad7134_ext_info_read, @@ -139,11 +176,50 @@ struct ad4134_state { struct gpio_desc *cs_gpio; unsigned int odr; + unsigned int filter_type; unsigned long sys_clk_rate; int refin_mv; int output_frame; }; +static int ad7134_set_dig_fil(struct iio_dev *dev, + const struct iio_chan_spec *chan, + unsigned int filter) +{ + struct ad4134_state *st = iio_priv(dev); + int ret; + + st->filter_type = filter; + gpiod_set_value_cansleep(st->cs_gpio, 1); + + ret = regmap_update_bits(st->regmap, AD4134_CHAN_DIG_FILTER_SEL_REG, + AD4134_CHAN_DIG_FILTER_SEL_MASK, + FIELD_PREP(AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH0, filter) | + FIELD_PREP(AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH1, filter) | + FIELD_PREP(AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH2, filter) | + FIELD_PREP(AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH3, filter)); + + gpiod_set_value_cansleep(st->cs_gpio, 0); + + if (ret) + return ret; + return 0; +} + +static int ad7134_get_dig_fil(struct iio_dev *dev, + const struct iio_chan_spec *chan) +{ + struct ad4134_state *st = iio_priv(dev); + int ret; + unsigned int readval; + + ret = regmap_read(st->regmap, AD4134_CHAN_DIG_FILTER_SEL_REG, &readval); + if (ret) + return ret; + + return FIELD_GET(AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH0, readval); +} + static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, uintptr_t private, const struct iio_chan_spec *chan, char *buf) @@ -436,10 +512,22 @@ static int ad4134_setup(struct ad4134_state *st) if (ret) return ret; - return regmap_update_bits(st->regmap, AD4134_DEVICE_CONFIG_REG, + ret = regmap_update_bits(st->regmap, AD4134_DEVICE_CONFIG_REG, AD4134_DEVICE_CONFIG_POWER_MODE_MASK, FIELD_PREP(AD4134_DEVICE_CONFIG_POWER_MODE_MASK, AD4134_POWER_MODE_HIGH_PERF)); + if (ret) + return ret; + + ret = regmap_update_bits(st->regmap, AD4134_CHAN_DIG_FILTER_SEL_REG, + AD4134_CHAN_DIG_FILTER_SEL_MASK, + FIELD_PREP(AD4134_CHAN_DIG_FILTER_SEL_MASK, + AD4134_SINC6_FILTER)); + + if (ret) + return ret; + + return 0; } static const struct regmap_config ad4134_regmap_config = { From 71d1f87e9d6c2441e5a2514c95bddba642884ade Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 17:57:47 -0300 Subject: [PATCH 10/75] iio: adc: ad4134: Add support for device synchronization Signed-off-by: Ioan-daniel Pop Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index b5d4e24d529cdb..222ba0b382ca07 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -26,6 +26,11 @@ #define AD4134_NAME "ad4134" +#define AD4134_IF_CONFIG_B_REG 0x01 +#define AD4134_IF_CONFIG_B_SINGLE_INSTR BIT(7) +#define AD4134_IF_CONFIG_B_MASTER_SLAVE_RD_CTRL BIT(5) +#define AD4134_IF_CONFIG_B_RESET BIT(1) + #define AD4134_DEVICE_CONFIG_REG 0x02 #define AD4134_DEVICE_CONFIG_POWER_MODE_MASK BIT(0) #define AD4134_POWER_MODE_HIGH_PERF 0b1 @@ -107,6 +112,11 @@ static const char * const ad7134_filter_enum[] = { .ext_info = _ext_info, \ } +static ssize_t ad7134_set_sync(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len); +static ssize_t ad7134_get_sync(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, char *buf); static int ad7134_set_dig_fil(struct iio_dev *dev, const struct iio_chan_spec *chan, unsigned int filter); @@ -137,6 +147,12 @@ static struct iio_chan_spec_ext_info ad7134_ext_info[] = { .shared = IIO_SHARED_BY_ALL, .private = ODR_SET_FREQ, }, + { + .name = "ad7134_sync", + .write = ad7134_set_sync, + .read = ad7134_get_sync, + .shared = IIO_SHARED_BY_ALL, + }, { }, }; @@ -182,6 +198,30 @@ struct ad4134_state { int output_frame; }; +static ssize_t ad7134_get_sync(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, char *buf) +{ + return sprintf(buf, "enable\n"); +} + +static ssize_t ad7134_set_sync(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct ad4134_state *st = iio_priv(indio_dev); + int ret; + + gpiod_set_value_cansleep(st->cs_gpio, 1); + ret = regmap_update_bits(st->regmap, AD4134_IF_CONFIG_B_REG, + (AD4134_IF_CONFIG_B_RESET | AD4134_IF_CONFIG_B_SINGLE_INSTR), + (AD4134_IF_CONFIG_B_RESET | AD4134_IF_CONFIG_B_SINGLE_INSTR)); + if (ret) + return ret; + gpiod_set_value_cansleep(st->cs_gpio, 0); + + return ret ? ret : len; +} + static int ad7134_set_dig_fil(struct iio_dev *dev, const struct iio_chan_spec *chan, unsigned int filter) From 3d3742a8e8f9693d92c817775c3a3dd5e2dfc9b6 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 5 Jun 2024 16:04:10 -0300 Subject: [PATCH 11/75] iio: adc: ad4134: Get number of ADCs available Count the number os AD4134/AD7134 compatibles under the SPI controller node to determine how many ADCs are present in hardware. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 222ba0b382ca07..c911bdd7713a13 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -459,6 +459,23 @@ static const struct iio_buffer_setup_ops ad4134_buffer_ops = { .predisable = ad4134_buffer_predisable, }; +static int ad4134_get_ADC_count(struct ad4134_state *st) +{ + struct device *controller_dev = &st->spi->controller->dev; + struct fwnode_handle *child; + unsigned int adc_count = 0; + + device_for_each_child_node(controller_dev, child) { + if (fwnode_property_match_string(child, "compatible", + "adi,ad4134") >= 0) + adc_count++; + if (fwnode_property_match_string(child, "compatible", + "adi,ad7134") >= 0) + adc_count++; + } + return adc_count; +} + static void ad4134_disable_regulators(void *data) { struct ad4134_state *st = data; From 2749425a972528b87739e43574eb95f73db99f03 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 13:42:53 -0300 Subject: [PATCH 12/75] iio: adc: ad4134: Simplify with scoped child node iterator Use scoped child device node iterator to simplify code. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index c911bdd7713a13..6565e5674d5ba0 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -462,10 +462,9 @@ static const struct iio_buffer_setup_ops ad4134_buffer_ops = { static int ad4134_get_ADC_count(struct ad4134_state *st) { struct device *controller_dev = &st->spi->controller->dev; - struct fwnode_handle *child; unsigned int adc_count = 0; - device_for_each_child_node(controller_dev, child) { + device_for_each_child_node_scoped(controller_dev, child) { if (fwnode_property_match_string(child, "compatible", "adi,ad4134") >= 0) adc_count++; From b20dcf6668e19f9c29ced246b24e4675f9b2a976 Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Tue, 2 Jul 2024 18:00:47 -0300 Subject: [PATCH 13/75] iio: adc: ad4134: Add support for dual ADC setups Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 93 ++++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 6565e5674d5ba0..dd76923ade6668 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -163,16 +163,37 @@ static struct iio_chan_spec_ext_info ad7134_ext_info[] = { AD4134_CHANNEL(3, _realbits, _storebits, ad7134_ext_info), \ } +#define AD4134_DUO_CHAN_SET(_realbits, _storebits) { \ + AD4134_CHANNEL(0, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(1, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(2, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(3, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(4, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(5, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(6, _realbits, _storebits, ad7134_ext_info), \ + AD4134_CHANNEL(7, _realbits, _storebits, ad7134_ext_info), \ +} + static const struct iio_chan_spec ad4134_16_chan_set[] = AD4134_CHAN_SET(16, 16); static const struct iio_chan_spec ad4134_16CRC_chan_set[] = AD4134_CHAN_SET(16, 24); static const struct iio_chan_spec ad4134_24_chan_set[] = AD4134_CHAN_SET(24, 24); static const struct iio_chan_spec ad4134_24CRC_chan_set[] = AD4134_CHAN_SET(24, 32); +static const struct iio_chan_spec ad4134_16_duo_chan_set[] = AD4134_DUO_CHAN_SET(16, 16); +static const struct iio_chan_spec ad4134_16CRC_duo_chan_set[] = AD4134_DUO_CHAN_SET(16, 24); +static const struct iio_chan_spec ad4134_24_duo_chan_set[] = AD4134_DUO_CHAN_SET(24, 24); +static const struct iio_chan_spec ad4134_24CRC_duo_chan_set[] = AD4134_DUO_CHAN_SET(24, 32); + static const unsigned long ad4134_channel_masks[] = { GENMASK(ARRAY_SIZE(ad4134_16_chan_set) - 1, 0), 0, }; +static const unsigned long ad4134_duo_channel_masks[] = { + GENMASK(ARRAY_SIZE(ad4134_16_duo_chan_set) - 1, 0), + 0, +}; + struct ad4134_state { struct fwnode_handle *spi_engine_fwnode; struct regmap *regmap; @@ -639,6 +660,7 @@ static int ad4134_probe(struct spi_device *spi) struct fwnode_handle *fwnode = dev_fwnode(dev); struct iio_dev *indio_dev; struct ad4134_state *st; + bool ad4134_duo; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -657,6 +679,8 @@ static int ad4134_probe(struct spi_device *spi) st->regulators[AD4134_IOVDD_REGULATOR].supply = "iovdd"; st->regulators[AD4134_REFIN_REGULATOR].supply = "refin"; + ad4134_duo = ad4134_get_ADC_count(st) == 2; + st->output_frame = AD4134_DATA_PACKET_24BIT_FRAME; ret = device_property_match_property_string(dev, "adi,adc-frame", ad4134_frame_config, @@ -668,20 +692,48 @@ static int ad4134_probe(struct spi_device *spi) switch (st->output_frame) { case AD4134_DATA_PACKET_16BIT_FRAME: - indio_dev->channels = ad4134_16_chan_set; - indio_dev->num_channels = ARRAY_SIZE(ad4134_16_chan_set); + if (ad4134_duo) { + indio_dev->channels = ad4134_16_duo_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_16_duo_chan_set); + indio_dev->available_scan_masks = ad4134_duo_channel_masks; + } else { + indio_dev->channels = ad4134_16_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_16_chan_set); + indio_dev->available_scan_masks = ad4134_channel_masks; + } break; case AD4134_DATA_PACKET_16BIT_CRC6_FRAME: - indio_dev->channels = ad4134_16CRC_chan_set; - indio_dev->num_channels = ARRAY_SIZE(ad4134_16CRC_chan_set); + if (ad4134_duo) { + indio_dev->channels = ad4134_16CRC_duo_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_16CRC_duo_chan_set); + indio_dev->available_scan_masks = ad4134_duo_channel_masks; + } else { + indio_dev->channels = ad4134_16CRC_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_16CRC_chan_set); + indio_dev->available_scan_masks = ad4134_channel_masks; + } break; case AD4134_DATA_PACKET_24BIT_FRAME: - indio_dev->channels = ad4134_24_chan_set; - indio_dev->num_channels = ARRAY_SIZE(ad4134_24_chan_set); + if (ad4134_duo) { + indio_dev->channels = ad4134_24_duo_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_24_duo_chan_set); + indio_dev->available_scan_masks = ad4134_duo_channel_masks; + } else { + indio_dev->channels = ad4134_24_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_24_chan_set); + indio_dev->available_scan_masks = ad4134_channel_masks; + } break; case AD4134_DATA_PACKET_24BIT_CRC6_FRAME: - indio_dev->channels = ad4134_24CRC_chan_set; - indio_dev->num_channels = ARRAY_SIZE(ad4134_24CRC_chan_set); + if (ad4134_duo) { + indio_dev->channels = ad4134_24CRC_duo_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_24CRC_duo_chan_set); + indio_dev->available_scan_masks = ad4134_duo_channel_masks; + } else { + indio_dev->channels = ad4134_24CRC_chan_set; + indio_dev->num_channels = ARRAY_SIZE(ad4134_24CRC_chan_set); + indio_dev->available_scan_masks = ad4134_channel_masks; + } break; default: return dev_err_probe(dev, -EINVAL, @@ -702,22 +754,25 @@ static int ad4134_probe(struct spi_device *spi) if (IS_ERR(st->regmap)) return PTR_ERR(st->regmap); - indio_dev->channels = ad4134_channels; - indio_dev->num_channels = ARRAY_SIZE(ad4134_channels); - indio_dev->available_scan_masks = ad4134_channel_masks; - indio_dev->name = AD4134_NAME; - indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE; - indio_dev->setup_ops = &ad4134_buffer_ops; - indio_dev->info = &ad4134_info; - ret = ad4134_setup(st); if (ret) return ret; ret = devm_iio_dmaengine_buffer_setup(dev, indio_dev, "rx"); - if (ret) - return dev_err_probe(dev, ret, - "Failed to allocate IIO DMA buffer\n"); + if (ret) { + indio_dev->channels = 0; + indio_dev->num_channels = 0; + indio_dev->available_scan_masks = 0; + indio_dev->name = spi->dev.of_node->name; + indio_dev->modes = 0; + indio_dev->setup_ops = 0; + return devm_iio_device_register(dev, indio_dev); + } + + indio_dev->name = spi->dev.of_node->name; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE; + indio_dev->setup_ops = &ad4134_buffer_ops; + indio_dev->info = &ad4134_info; st->spi_engine_fwnode = fwnode_find_reference(fwnode, "adi,spi-engine", 0); if (IS_ERR(st->spi_engine_fwnode)) From 7cf41305b380a95f271cb08e76b2523c18e7e59d Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 25 Jul 2024 15:23:50 -0300 Subject: [PATCH 14/75] iio: adc: ad4134: Assign iio_info for all devices __iio_device_register() fails if the device has no initialized info field. Assign ad4134_info to all devices (even those that don't expose the channels). Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index dd76923ade6668..53d71bbfe7e0f6 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -758,21 +758,19 @@ static int ad4134_probe(struct spi_device *spi) if (ret) return ret; + indio_dev->name = spi->dev.of_node->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &ad4134_info; + ret = devm_iio_dmaengine_buffer_setup(dev, indio_dev, "rx"); if (ret) { indio_dev->channels = 0; indio_dev->num_channels = 0; indio_dev->available_scan_masks = 0; - indio_dev->name = spi->dev.of_node->name; - indio_dev->modes = 0; - indio_dev->setup_ops = 0; return devm_iio_device_register(dev, indio_dev); } - indio_dev->name = spi->dev.of_node->name; - indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE; indio_dev->setup_ops = &ad4134_buffer_ops; - indio_dev->info = &ad4134_info; st->spi_engine_fwnode = fwnode_find_reference(fwnode, "adi,spi-engine", 0); if (IS_ERR(st->spi_engine_fwnode)) From b77cd44a6dc93377472a706960d91db95e1a980c Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Fri, 29 Mar 2024 22:41:09 +0200 Subject: [PATCH 15/75] iio: adc: ad4134: Add functionality for PWM trigger and make ODR PWM optional ODR PWM is used for triggering SPI-Engine offload which then allows adjustable ADC sample rate. However, there exist AD7134 evaluation boards that featute two AD7134 devices that can synchronize to do simultaneous sampling. In those setups, the SPI-Engine offload trigger can be shared between devices and thus the PWM becomes optional for one of them. Also, it is expected that there will be evaluation boards featuring two AD4134 in the future. Extract PWM setup to own routine and make PWMs optional. Co-developed-by: Dragos Bogdan Signed-off-by: Dragos Bogdan Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 102 +++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 53d71bbfe7e0f6..069baf7b029a40 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -200,6 +200,7 @@ struct ad4134_state { struct spi_device *spi; struct spi_device *spi_engine; struct pwm_device *odr_pwm; + struct pwm_device *trigger_pwm; struct regulator_bulk_data regulators[AD4134_NUM_REGULATORS]; /* @@ -308,13 +309,21 @@ static int ad4134_samp_freq_avail[] = { AD4134_ODR_MIN, 1, AD4134_ODR_MAX }; static int _ad4134_set_odr(struct ad4134_state *st, unsigned int odr) { - struct pwm_state state; + struct pwm_state state_odr; + struct pwm_state state_trigger; int ret; + u64 ref_clk_period_ps = DIV_ROUND_CLOSEST_ULL(PICO, st->sys_clk_rate); + + if (!st->odr_pwm) + return 0; + + if (!st->trigger_pwm) + return 0; if (odr < AD4134_ODR_MIN || odr > AD4134_ODR_MAX) return -EINVAL; - pwm_get_state(st->odr_pwm, &state); + pwm_get_state(st->odr_pwm, &state_odr); /* * fDIGCLK = fSYSCLK / 2 @@ -322,15 +331,26 @@ static int _ad4134_set_odr(struct ad4134_state *st, unsigned int odr) * tODR_HIGH_TIME = 3 * tDIGCLK * See datasheet page 10, Table 3. Data Interface Timing with Gated DCLK. */ - state.duty_cycle = DIV_ROUND_CLOSEST_ULL(6ULL * NSEC_PER_SEC, st->sys_clk_rate); - state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, odr); + state_odr.duty_cycle = DIV_ROUND_CLOSEST_ULL(6ULL * NSEC_PER_SEC, st->sys_clk_rate); + state_odr.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, odr); - ret = pwm_apply_might_sleep(st->odr_pwm, &state); + ret = pwm_apply_might_sleep(st->odr_pwm, &state_odr); if (ret) return ret; st->odr = odr; + pwm_get_state(st->trigger_pwm, &state_trigger); + + state_trigger.duty_cycle = ref_clk_period_ps; + state_trigger.period = DIV_ROUND_CLOSEST_ULL(PICO, odr); + state_trigger.time_unit = PWM_UNIT_PSEC; + state_trigger.phase = state_odr.duty_cycle - DIV_ROUND_CLOSEST_ULL(PICO * 10, + st->sys_clk_rate); + ret = pwm_apply_state(st->trigger_pwm, &state_trigger); + if (ret) + return ret; + return 0; } @@ -339,6 +359,12 @@ static int ad4134_set_odr(struct iio_dev *indio_dev, unsigned int odr) struct ad4134_state *st = iio_priv(indio_dev); int ret; + if (IS_ERR(st->odr_pwm)) + return 0; + + if (IS_ERR(st->trigger_pwm)) + return 0; + ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; @@ -508,6 +534,53 @@ static void ad4134_disable_pwm(void *data) pwm_disable(data); } +static int ad4134_pwm_setup(struct ad4134_state *st) +{ + struct device *dev = &st->spi->dev; + int ret; + + if (!device_property_present(&st->spi->dev, "pwms")) + return 0; + + st->odr_pwm = devm_pwm_get(dev, "odr_pwm"); + if (IS_ERR(st->odr_pwm)) + dev_err(&st->spi->dev, "Failed to find ODR PWM\n"); + + ret = devm_add_action_or_reset(dev, ad4134_disable_pwm, st->odr_pwm); + if (ret) + return dev_err_probe(dev, ret, + "Failed to add ODR PWM disable action\n"); + + st->trigger_pwm = devm_pwm_get(dev, "trigger_pwm"); + if (IS_ERR(st->trigger_pwm)) + dev_err(&st->spi->dev, "Failed to find trigger PWM\n"); + + ret = devm_add_action_or_reset(dev, ad4134_disable_pwm, st->trigger_pwm); + if (ret) + return dev_err_probe(dev, ret, + "Failed to add ODR PWM disable action\n"); + + fsleep(3000); + if (!IS_ERR(st->odr_pwm) & !IS_ERR(st->trigger_pwm)) { + ret = _ad4134_set_odr(st, AD4134_ODR_DEFAULT); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize ODR\n"); + + ret = pwm_enable(st->odr_pwm); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable ODR PWM\n"); + + ret = pwm_enable(st->trigger_pwm); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable trigger PWM\n"); + } else { + dev_warn(dev, "Failed to find ODR PWM\n"); + } + + return 0; +} + static int ad4134_setup(struct ad4134_state *st) { struct device *dev = &st->spi->dev; @@ -515,7 +588,7 @@ static int ad4134_setup(struct ad4134_state *st) struct clk *clk; int ret; - clk = devm_clk_get_enabled(dev, "sys_clk"); + clk = devm_clk_get_enabled(dev, "cnv_ext_clk"); if (IS_ERR(clk)) return dev_err_probe(dev, PTR_ERR(clk), "Failed to find SYS clock\n"); @@ -523,6 +596,7 @@ static int ad4134_setup(struct ad4134_state *st) if (!st->sys_clk_rate) return dev_err_probe(dev, -EINVAL, "Failed to get SYS clock rate\n"); + st->sys_clk_rate = clk_round_rate(clk, 100000000); ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regulators), st->regulators); if (ret) @@ -557,24 +631,10 @@ static int ad4134_setup(struct ad4134_state *st) gpiod_set_value_cansleep(reset_gpio, 0); - st->odr_pwm = devm_pwm_get(dev, "odr_pwm"); - if (IS_ERR(st->odr_pwm)) - return dev_err_probe(dev, PTR_ERR(st->odr_pwm), - "Failed to find ODR PWM\n"); - - ret = _ad4134_set_odr(st, AD4134_ODR_DEFAULT); - if (ret) - return dev_err_probe(dev, ret, "Failed to initialize ODR\n"); - - ret = pwm_enable(st->odr_pwm); + ret = ad4134_pwm_setup(st); if (ret) return ret; - ret = devm_add_action_or_reset(dev, ad4134_disable_pwm, st->odr_pwm); - if (ret) - return dev_err_probe(dev, ret, - "Failed to add ODR PWM disable action\n"); - ret = regmap_update_bits(st->regmap, AD4134_DATA_PACKET_CONFIG_REG, AD4134_DATA_PACKET_CONFIG_FRAME_MASK, FIELD_PREP(AD4134_DATA_PACKET_CONFIG_FRAME_MASK, From 5940fae7b6b86fc8dd2dec2106d87461d583a81f Mon Sep 17 00:00:00 2001 From: Ioan-daniel Pop Date: Thu, 13 Jun 2024 23:11:19 -0300 Subject: [PATCH 16/75] iio: adc: ad4134: Implement GPIO controller interface Make AD4134/AD7134 devices able to provide GPIOs as a GPIO controller. AD4134/AD7134 GPIO controller capability is used by the CN0561 project. Signed-off-by: Ioan-daniel Pop Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 106 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 069baf7b029a40..d64486490f7d8a 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,11 @@ #define AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH2 GENMASK(5, 4) #define AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH3 GENMASK(7, 6) +#define AD4134_GPIO_INPUT(x) 0x00 +#define AD4134_GPIO_OUTPUT(x) BIT(x) +#define AD4134_GPIO_DIR_CONTROL 0x20 +#define AD4134_GPIO_DATA 0x21 + #define AD4134_SINC6_FILTER 0b01010101 #define AD4134_ODR_MIN 10 @@ -212,6 +218,7 @@ struct ad4134_state { struct spi_message buf_read_msg; struct spi_transfer buf_read_xfer; struct gpio_desc *cs_gpio; + struct gpio_chip gpiochip; unsigned int odr; unsigned int filter_type; @@ -409,6 +416,98 @@ static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, return ret ? ret : len; } +static int ad4134_input_gpio(struct gpio_chip *chip, unsigned int offset) +{ + struct ad4134_state *st = gpiochip_get_data(chip); + int ret; + + mutex_lock(&st->lock); + ret = regmap_update_bits(st->regmap, AD4134_GPIO_DIR_CONTROL, + BIT(offset), AD4134_GPIO_INPUT(offset)); + + mutex_unlock(&st->lock); + + return ret; +} + +static int ad4134_output_gpio(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct ad4134_state *st = gpiochip_get_data(chip); + int ret; + + mutex_lock(&st->lock); + + ret = regmap_update_bits(st->regmap, AD4134_GPIO_DIR_CONTROL, + BIT(offset), AD4134_GPIO_OUTPUT(offset)); + if (ret < 0) + goto out; + + ret = regmap_update_bits(st->regmap, AD4134_GPIO_DATA, BIT(offset), + (value << offset)); +out: + mutex_unlock(&st->lock); + + return ret; +} + +static int ad4134_get_gpio(struct gpio_chip *chip, unsigned int offset) +{ + struct ad4134_state *st = gpiochip_get_data(chip); + unsigned int val; + int ret; + + mutex_lock(&st->lock); + ret = regmap_read(st->regmap, AD4134_GPIO_DIR_CONTROL, &val); + if (ret < 0) + goto out; + + ret = regmap_read(st->regmap, AD4134_GPIO_DATA, &val); + if (ret < 0) + goto out; + + ret = !!(val & BIT(offset)); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static void ad4134_set_gpio(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct ad4134_state *st = gpiochip_get_data(chip); + unsigned int val; + int ret; + + mutex_lock(&st->lock); + ret = regmap_read(st->regmap, AD4134_GPIO_DIR_CONTROL, &val); + if (ret < 0) + goto out; + + if (val & BIT(offset)) + regmap_update_bits(st->regmap, AD4134_GPIO_DATA, BIT(offset), + (value << offset)); + +out: + mutex_unlock(&st->lock); +} + +int ad4134_gpio_setup(struct ad4134_state *st) +{ + st->gpiochip.label = "ad4134"; + st->gpiochip.base = -1; + st->gpiochip.ngpio = 8; + st->gpiochip.parent = &st->spi->dev; + st->gpiochip.can_sleep = true; + st->gpiochip.direction_input = ad4134_input_gpio; + st->gpiochip.direction_output = ad4134_output_gpio; + st->gpiochip.get = ad4134_get_gpio; + st->gpiochip.set = ad4134_set_gpio; + + return devm_gpiochip_add_data(&st->spi->dev, &st->gpiochip, st); +} + static int ad4134_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) @@ -818,6 +917,13 @@ static int ad4134_probe(struct spi_device *spi) if (ret) return ret; + if (device_property_present(&st->spi->dev, "gpio-controller")) { + ret = ad4134_gpio_setup(st); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "Failed to setup GPIOs\n"); + } + indio_dev->name = spi->dev.of_node->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad4134_info; From 4cf6dd8247709944dd10cb3f844774aa51e0e9b8 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Jan 2025 18:24:33 -0300 Subject: [PATCH 17/75] iio: adc: ad4134: Complement comment about ODR PWM duty cycle Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index d64486490f7d8a..9a9ebe1248bca6 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -337,6 +337,21 @@ static int _ad4134_set_odr(struct ad4134_state *st, unsigned int odr) * tDIGCLK = 1s / fDIGCLK * tODR_HIGH_TIME = 3 * tDIGCLK * See datasheet page 10, Table 3. Data Interface Timing with Gated DCLK. + * + * fSYSCLK is obtained from cnv_ext_clk clock provided in device tree. + * cnv_ext_clk is expected provide 100 MHz clock. Thus, + * fSYSCLK = sys_clk_rate = 100 MHz + * fDIGCLK = 50 MHz + * tDIGCLK = 0,02 * 10^-6= 20 * 10^-9 s + * tODR_HIGH_TIME = 60 * 10^-9 s = 60 ns + * + * With sys_clk_rate be set to 100 MHz, + * state_odr.duty_cycle = (CONST * 10^12)/sys_clk_rate + * = (CONST * 10^12)/10^8 + * = CONST * 10^4 + * and we need CONST * 10^4 > 60 ns minimum tODR_HIGH_TIME. + * CONST is set to 13 so ODR signal stays high for 130 ns which is + * enough meet the 60 ns minimum plus some latency. */ state_odr.duty_cycle = DIV_ROUND_CLOSEST_ULL(6ULL * NSEC_PER_SEC, st->sys_clk_rate); state_odr.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, odr); From fd6012dfd46595305c6f5c3387a5e3ae297002da Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Mon, 17 Feb 2025 13:14:40 -0300 Subject: [PATCH 18/75] iio: adc: ad4134: Adjust ODR PWM duty_cycle Change the duty cycle of the AXI PWM generator used as ODR signal to be equal to dev_ad4134 branch that is said to work for single AD4134 device setup. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 9a9ebe1248bca6..b1a40bc2db135d 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -367,7 +367,7 @@ static int _ad4134_set_odr(struct ad4134_state *st, unsigned int odr) state_trigger.duty_cycle = ref_clk_period_ps; state_trigger.period = DIV_ROUND_CLOSEST_ULL(PICO, odr); state_trigger.time_unit = PWM_UNIT_PSEC; - state_trigger.phase = state_odr.duty_cycle - DIV_ROUND_CLOSEST_ULL(PICO * 10, + state_trigger.phase = state_odr.duty_cycle - DIV_ROUND_CLOSEST_ULL(PICO * 12, st->sys_clk_rate); ret = pwm_apply_state(st->trigger_pwm, &state_trigger); if (ret) From 0150bf10fcf842dece9013289fb52ba7908dcb50 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Mon, 17 Feb 2025 13:17:05 -0300 Subject: [PATCH 19/75] iio: adc: ad4134: Don't call clk_round_rate() to set sys_clk_rate Remove call to sys_clk_rate(). With that ad4134_setup() becomes essentially equal to ad4134_setup() in dev_ad4134 branch which is said to work for AD4134 single device setup. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index b1a40bc2db135d..905f291f980f3a 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -710,7 +710,6 @@ static int ad4134_setup(struct ad4134_state *st) if (!st->sys_clk_rate) return dev_err_probe(dev, -EINVAL, "Failed to get SYS clock rate\n"); - st->sys_clk_rate = clk_round_rate(clk, 100000000); ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regulators), st->regulators); if (ret) From 8b919502bc58765cb90cafa63393d8e66276004d Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 19 Feb 2025 10:21:17 -0300 Subject: [PATCH 20/75] iio: adc: ad4134: Set storagebits to 32 Previous implementation that was said to work has all IIO channels configured to use 32-bit storage for each buffer element. That was the last significant remaining difference from dev_ad4134 branch. Preliminary tests suggests the results are now similar to that working version. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 905f291f980f3a..635a5d201f7e8b 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -112,7 +112,7 @@ static const char * const ad7134_filter_enum[] = { .scan_type = { \ .sign = 's', \ .realbits = (_realbits), \ - .storagebits = (_storebits), \ + .storagebits = 32, \ .shift = ((_storebits) - (_realbits)) \ }, \ .ext_info = _ext_info, \ From 8298aa2824af2a750dfb8fd5773ed31a737f0b23 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 26 Feb 2025 15:38:15 -0300 Subject: [PATCH 21/75] iio: adc: ad4134: Set transfer bits_per_word equal to realbits + CRC bits Set SPI transfer bits_per_word equal to number of ADC precision bits (realbits) plus number of CRC bits. _storebits == _realbits + CRC bits .shift = ((_storebits) - (_realbits)) Thus, .realbits + .shift == total number of data bits to transfer. Note .storagebits = 32 to cope with DMA datum element size. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 635a5d201f7e8b..6f41b616e0a537 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -919,7 +919,12 @@ static int ad4134_probe(struct spi_device *spi) */ st->buf_read_xfer.rx_buf = (void *)-1; st->buf_read_xfer.len = 1; - st->buf_read_xfer.bits_per_word = indio_dev->channels->scan_type.storagebits; + /* + * TODO implement multiple scan_type structs so storagebits and + * bits_per_word can be set differently for DMA and non-DMA able cases? + */ + st->buf_read_xfer.bits_per_word = indio_dev->channels->scan_type.realbits + + indio_dev->channels->scan_type.shift; spi_message_init_with_transfers(&st->buf_read_msg, &st->buf_read_xfer, 1); From 648fc691336c7b4d9d17bf6d3fd88918b3fe3bcb Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 18 Nov 2025 09:25:04 -0300 Subject: [PATCH 22/75] iio: adc: ad4134: Update attribute name from "ad7134_sync" to "ad4134_sync" Update dual device setup synchronization attribute name to "ad4134_sync" according to request from Ahmet Alincak and the Apps team. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 6f41b616e0a537..40e98b12fc7e18 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -154,7 +154,7 @@ static struct iio_chan_spec_ext_info ad7134_ext_info[] = { .private = ODR_SET_FREQ, }, { - .name = "ad7134_sync", + .name = "ad4134_sync", .write = ad7134_set_sync, .read = ad7134_get_sync, .shared = IIO_SHARED_BY_ALL, From b578a8a503c10352767ea445002171b8af60a121 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 13:41:25 -0300 Subject: [PATCH 23/75] iio: adc: ad4134: Set static visibility GPIO setup routine Set static visibility to AD4134 GPIO setup routine so to fix build warning. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 40e98b12fc7e18..9503c73220a2d9 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -508,7 +508,7 @@ static void ad4134_set_gpio(struct gpio_chip *chip, unsigned int offset, int val mutex_unlock(&st->lock); } -int ad4134_gpio_setup(struct ad4134_state *st) +static int ad4134_gpio_setup(struct ad4134_state *st) { st->gpiochip.label = "ad4134"; st->gpiochip.base = -1; From 3a5bf2d8efed0c8b557386b3c7df0678c6977d12 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 17 Mar 2026 11:04:03 -0300 Subject: [PATCH 24/75] iio: adc: ad4134: [WIP] Completeley rewrite SPI offload support Old AD4134 offload support doesn't work anymore with new in-kernel interfaces. Rewrite AD4134 offload support with upstream quality code. iio: adc: ad4134: [WIP] Drop no longer used _ad4134_set_odr() _ad4134_set_odr() was replaced by ad4134_update_conversion_rate(). iio: adc: ad4134: Mix/merge new offload support with old setup procedures iio: adc: ad4134: [WIP] Drop old no longer used PWM devices iio: adc: ad4134: [WIP] Adapt to weird dt configuration iio: adc: ad4134: Check adi,spi-engine instead of dma for offload connection With the update to upstream offload support and trigger sources, the ADC dt node no longer keeps references to DMA. What actually indicates the connection to SPI Engine is the adi,spi-engine property. Check the spi-engine prop to decide whether to configure offload or not. iio: adc: ad4134: Drop old offload support iio: adc: ad4134: Add ad4134_offload_attribute_group iio: adc: ad4134: Set st->num_dout_lines = 4 Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 489 +++++++++++++++++++++++++++------------ 1 file changed, 341 insertions(+), 148 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 9503c73220a2d9..a135dfaa30fd3a 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -25,6 +25,21 @@ #include #include +#include + +#include +#include +#include +#include + +#define AD4134_DCLK_RISING_OFFSET_NS 8 +#define AD4134_MIN_ODR_FREQ_HZ 10 +#define AD4134_MAX_ODR_FREQ_HZ (1496 * HZ_PER_KHZ) + +#define AD4134_SPI_MAX_XFER_LEN 3 +#define AD4134_NUM_CHANNELS 4 +#define AD4134_CHAN_PRECISION_BITS 24 + #define AD4134_NAME "ad4134" #define AD4134_IF_CONFIG_B_REG 0x01 @@ -205,8 +220,19 @@ struct ad4134_state { struct regmap *regmap; struct spi_device *spi; struct spi_device *spi_engine; - struct pwm_device *odr_pwm; - struct pwm_device *trigger_pwm; + + unsigned long sys_clk_hz; + + struct spi_transfer xfers[AD4134_NUM_CHANNELS]; + struct spi_message msg; + + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + struct spi_offload_trigger_config offload_trigger_config; + struct pwm_device *odr_trigger; + struct pwm_waveform odr_wf; + unsigned int odr_hz; + struct regulator_bulk_data regulators[AD4134_NUM_REGULATORS]; /* @@ -216,7 +242,6 @@ struct ad4134_state { struct mutex lock; struct spi_message buf_read_msg; - struct spi_transfer buf_read_xfer; struct gpio_desc *cs_gpio; struct gpio_chip gpiochip; @@ -225,6 +250,8 @@ struct ad4134_state { unsigned long sys_clk_rate; int refin_mv; int output_frame; + u8 num_dout_lines; + }; static ssize_t ad7134_get_sync(struct iio_dev *indio_dev, uintptr_t private, @@ -314,65 +341,320 @@ static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, static int ad4134_samp_freq_avail[] = { AD4134_ODR_MIN, 1, AD4134_ODR_MAX }; -static int _ad4134_set_odr(struct ad4134_state *st, unsigned int odr) +/* + * Hardcoded 32-bit storagebits because the currently available HDL only + * supports that. + */ +#define AD4134_OFFLOAD_CHANNEL(_index) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_index), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = (_index), \ + .scan_type = { \ + .sign = 's', \ + .storagebits = 32, \ + .realbits = AD4134_CHAN_PRECISION_BITS, \ + .endianness = IIO_CPU, \ + }, \ +} + +/* + * It's not possible for software to record when offloaded SPI transfers run so + * no additional timestamp channel is added. + */ +static const struct iio_chan_spec ad4134_offload_chan_set[] = { + AD4134_OFFLOAD_CHANNEL(0), + AD4134_OFFLOAD_CHANNEL(1), + AD4134_OFFLOAD_CHANNEL(2), + AD4134_OFFLOAD_CHANNEL(3), +}; + +/* The chip converts and outputs all 4 channels on each sample request */ +static const unsigned long ad4134_offload_scan_masks[] = { + GENMASK(3, 0), + 0 +}; + +static const struct spi_offload_config ad4134_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + +static int ad4134_update_conversion_rate(struct ad4134_state *st, + unsigned int freq_hz) { - struct pwm_state state_odr; - struct pwm_state state_trigger; + struct spi_offload_trigger_config *config = &st->offload_trigger_config; + struct pwm_waveform odr_wf = { }; + u64 offload_period_ns; + u64 offload_offset_ns; + u64 odr_high_time_ns; + unsigned int odr_hz; + u64 target = 0; int ret; - u64 ref_clk_period_ps = DIV_ROUND_CLOSEST_ULL(PICO, st->sys_clk_rate); - if (!st->odr_pwm) - return 0; + /* + * Every ODR pulse causes each of the 4 ADCs within the AD4134 chip to + * take a sample simultaneously. The peripheral then outputs the data + * from all those channels over one, two, or four data output lanes. If + * the controller can fetch data from multiple lanes, the throughput is + * increased proportionally to the number of data lanes in use. + * Conversely, when multiple data lanes are enabled, the requested + * sampling frequency can be reached with slower ODR frequencies. + */ + odr_hz = freq_hz / st->num_dout_lines; + if (odr_hz < AD4134_MIN_ODR_FREQ_HZ || odr_hz > AD4134_MAX_ODR_FREQ_HZ) + return -EINVAL; - if (!st->trigger_pwm) - return 0; + odr_wf.period_length_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, odr_hz); + /* + * For an arbitrary system clock (fSYSCLK), we have a minimum ODR high + * time of 6/fSYSCLK derived from the device clock and data interface + * timing (with Gated DCLK) specifications. Set the PWM duty cycle to + * keep ODR up for at least that long. If the rounded PWM's value is + * less than the minimum required, increase the target value by 10 and + * attempt to round the waveform again, until the minimum is reached. + */ + odr_high_time_ns = div64_ul(6ULL * NANO, st->sys_clk_hz); + do { + odr_wf.duty_length_ns = target; + ret = pwm_round_waveform_might_sleep(st->odr_trigger, &odr_wf); + if (ret) + return ret; + target += 10; + } while (odr_wf.duty_length_ns < odr_high_time_ns); - if (odr < AD4134_ODR_MIN || odr > AD4134_ODR_MAX) + if (!in_range(odr_wf.period_length_ns, 2 * odr_high_time_ns, UINT_MAX)) return -EINVAL; - pwm_get_state(st->odr_pwm, &state_odr); + /* + * The controller fetches one sample per active lane each time the + * offload module is triggered. If multiple data lanes are enabled, the + * offload trigger frequency can be proportionally slower. + */ + offload_period_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, + odr_hz * st->num_dout_lines); + + config->periodic.frequency_hz = DIV_ROUND_UP_ULL(NSEC_PER_SEC, + offload_period_ns); + + /* + * For gated DCLK, the minimum required time between ODR rising edge + * and DCLK rising edge is the sum of ODR high time and ODR falling + * edge to DCLK rising edge time. Delay the offload trigger for at least + * that amount of time so the ADC sample data will be available when the + * SPI transfer begin. + */ + offload_offset_ns = odr_high_time_ns + AD4134_DCLK_RISING_OFFSET_NS; + do { + config->periodic.offset_ns = offload_offset_ns; + ret = spi_offload_trigger_validate(st->offload_trigger, config); + if (ret) + return ret; + + offload_offset_ns += 10; + } while (config->periodic.offset_ns < odr_high_time_ns + + AD4134_DCLK_RISING_OFFSET_NS); + + st->odr_wf = odr_wf; + st->odr_hz = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, odr_wf.period_length_ns); + + return 0; +} + +static ssize_t sampling_frequency_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad4134_state *st = iio_priv(dev_to_iio_dev(dev)); /* - * fDIGCLK = fSYSCLK / 2 - * tDIGCLK = 1s / fDIGCLK - * tODR_HIGH_TIME = 3 * tDIGCLK - * See datasheet page 10, Table 3. Data Interface Timing with Gated DCLK. - * - * fSYSCLK is obtained from cnv_ext_clk clock provided in device tree. - * cnv_ext_clk is expected provide 100 MHz clock. Thus, - * fSYSCLK = sys_clk_rate = 100 MHz - * fDIGCLK = 50 MHz - * tDIGCLK = 0,02 * 10^-6= 20 * 10^-9 s - * tODR_HIGH_TIME = 60 * 10^-9 s = 60 ns - * - * With sys_clk_rate be set to 100 MHz, - * state_odr.duty_cycle = (CONST * 10^12)/sys_clk_rate - * = (CONST * 10^12)/10^8 - * = CONST * 10^4 - * and we need CONST * 10^4 > 60 ns minimum tODR_HIGH_TIME. - * CONST is set to 13 so ODR signal stays high for 130 ns which is - * enough meet the 60 ns minimum plus some latency. + * If the controller can fetch data from multiple lanes, the throughput + * is increased proportionally to the number of data lanes in use. */ - state_odr.duty_cycle = DIV_ROUND_CLOSEST_ULL(6ULL * NSEC_PER_SEC, st->sys_clk_rate); - state_odr.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, odr); + return sysfs_emit(buf, "%u\n", st->odr_hz * st->num_dout_lines); +} - ret = pwm_apply_might_sleep(st->odr_pwm, &state_odr); +static ssize_t sampling_frequency_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad4134_state *st = iio_priv(indio_dev); + unsigned int val; + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + ret = kstrtouint(buf, 10, &val); if (ret) - return ret; + goto out_store; - st->odr = odr; + ret = ad4134_update_conversion_rate(st, val); - pwm_get_state(st->trigger_pwm, &state_trigger); +out_store: + iio_device_release_direct(indio_dev); + return ret ?: len; +} - state_trigger.duty_cycle = ref_clk_period_ps; - state_trigger.period = DIV_ROUND_CLOSEST_ULL(PICO, odr); - state_trigger.time_unit = PWM_UNIT_PSEC; - state_trigger.phase = state_odr.duty_cycle - DIV_ROUND_CLOSEST_ULL(PICO * 12, - st->sys_clk_rate); - ret = pwm_apply_state(st->trigger_pwm, &state_trigger); +static IIO_DEVICE_ATTR_RW(sampling_frequency, 0); + +static ssize_t sampling_frequency_available_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad4134_state *st = iio_priv(indio_dev); + + return sysfs_emit(buf, "[%u %u %lu]\n", + AD4134_MIN_ODR_FREQ_HZ * st->num_dout_lines, 1, + AD4134_MAX_ODR_FREQ_HZ * st->num_dout_lines); +} + +static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0); + +static struct attribute *ad4134_offload_attributes[] = { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +const struct attribute_group ad4134_offload_attribute_group = { + .attrs = ad4134_offload_attributes, +}; + +static void ad4134_prepare_offload_msg(struct iio_dev *indio_dev) +{ + struct ad4134_state *st = iio_priv(indio_dev); + unsigned int i; + + for (i = 0; i < AD4134_NUM_CHANNELS; i++) { + st->xfers[i].bits_per_word = AD4134_CHAN_PRECISION_BITS; + st->xfers[i].len = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS)); + st->xfers[i].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + } + + spi_message_init_with_transfers(&st->msg, st->xfers, AD4134_NUM_CHANNELS); +} + +static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4134_state *st = iio_priv(indio_dev); + int ret; + + ad4134_prepare_offload_msg(indio_dev); + st->msg.offload = st->offload; + ret = spi_optimize_message(st->spi, &st->msg); if (ret) return ret; + ret = pwm_set_waveform_might_sleep(st->odr_trigger, &st->odr_wf, false); + if (ret) + goto out_unoptimize; + + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, + &st->offload_trigger_config); + if (ret) + goto out_pwm_disable; + + return 0; + +out_pwm_disable: + pwm_disable(st->odr_trigger); +out_unoptimize: + spi_unoptimize_message(&st->msg); + + return 0; +} + +static int ad4134_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4134_state *st = iio_priv(indio_dev); + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + + pwm_disable(st->odr_trigger); + + spi_unoptimize_message(&st->msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ad4134_offload_buffer_setup_ops = { + .postenable = &ad4134_offload_buffer_postenable, + .predisable = &ad4134_offload_buffer_predisable, +}; + +static int ad4134_spi_offload_setup(struct iio_dev *indio_dev, + struct ad4134_state *st) +{ + struct device *dev = &st->spi->dev; + struct dma_chan *rx_dma; + + + st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_PERIODIC); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "failed to get offload trigger\n"); + + st->offload_trigger_config.type = SPI_OFFLOAD_TRIGGER_PERIODIC; + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "failed to get offload RX DMA\n"); + + return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); +} + +static int ad4134_pwm_get(struct ad4134_state *st) +{ + struct device *dev = &st->spi->dev; + + st->odr_trigger = devm_pwm_get(dev, NULL); + if (IS_ERR(st->odr_trigger)) + return dev_err_probe(dev, PTR_ERR(st->odr_trigger), + "failed to get ODR PWM\n"); + + pwm_disable(st->odr_trigger); + + return 0; +} + +static int ad4134_offload_buffer_setup(struct iio_dev *indio_dev, struct spi_device *spi) +{ + struct ad4134_state *st = iio_priv(indio_dev); + struct device *dev = &spi->dev; + int ret; + + st->offload = devm_spi_offload_get(dev, spi, &ad4134_offload_config); + ret = PTR_ERR_OR_ZERO(st->offload); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get offload\n"); + + + ret = ad4134_spi_offload_setup(indio_dev, st); + if (ret) + return dev_err_probe(dev, ret, + "failed to setup SPI offload\n"); + + ret = ad4134_pwm_get(st); + if (ret) + return dev_err_probe(dev, ret, "failed to get PWM: %d\n", ret); + + /* + * Start with a slower sampling rate so there is some room for + * adjusting the sampling frequency without hitting the maximum + * conversion rate. + */ + st->odr_hz = AD4134_MAX_ODR_FREQ_HZ >> 4; + ret = ad4134_update_conversion_rate(st, st->odr_hz); + if (ret) + return dev_err_probe(dev, ret, "failed to set offload samp freq\n"); + return 0; } @@ -381,10 +663,10 @@ static int ad4134_set_odr(struct iio_dev *indio_dev, unsigned int odr) struct ad4134_state *st = iio_priv(indio_dev); int ret; - if (IS_ERR(st->odr_pwm)) + if (IS_ERR(st->odr_trigger)) return 0; - if (IS_ERR(st->trigger_pwm)) + if (IS_ERR(st->offload_trigger)) return 0; ret = iio_device_claim_direct_mode(indio_dev); @@ -393,7 +675,7 @@ static int ad4134_set_odr(struct iio_dev *indio_dev, unsigned int odr) mutex_lock(&st->lock); - ret = _ad4134_set_odr(st, odr); + ret = ad4134_update_conversion_rate(st, odr); mutex_unlock(&st->lock); @@ -419,7 +701,7 @@ static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, if (ret) goto out; readin = clamp_t(long long, readin, 0, 1500000); - ret = _ad4134_set_odr(st, readin); + ret = ad4134_update_conversion_rate(st, readin); break; default: @@ -589,37 +871,10 @@ static const struct iio_info ad4134_info = { .read_raw = ad4134_read_raw, .read_avail = ad4134_read_avail, .write_raw = ad4134_write_raw, + .attrs = &ad4134_offload_attribute_group, .debugfs_reg_access = ad4134_reg_access, }; -static int ad4134_buffer_postenable(struct iio_dev *indio_dev) -{ - struct ad4134_state *st = iio_priv(indio_dev); - int ret; - - ret = legacy_spi_engine_offload_load_msg(st->spi_engine, &st->buf_read_msg); - if (ret) - return ret; - - legacy_spi_engine_offload_enable(st->spi_engine, true); - - return 0; -} - -static int ad4134_buffer_predisable(struct iio_dev *indio_dev) -{ - struct ad4134_state *st = iio_priv(indio_dev); - - legacy_spi_engine_offload_enable(st->spi_engine, false); - - return 0; -} - -static const struct iio_buffer_setup_ops ad4134_buffer_ops = { - .postenable = ad4134_buffer_postenable, - .predisable = ad4134_buffer_predisable, -}; - static int ad4134_get_ADC_count(struct ad4134_state *st) { struct device *controller_dev = &st->spi->controller->dev; @@ -643,57 +898,6 @@ static void ad4134_disable_regulators(void *data) regulator_bulk_disable(ARRAY_SIZE(st->regulators), st->regulators); } -static void ad4134_disable_pwm(void *data) -{ - pwm_disable(data); -} - -static int ad4134_pwm_setup(struct ad4134_state *st) -{ - struct device *dev = &st->spi->dev; - int ret; - - if (!device_property_present(&st->spi->dev, "pwms")) - return 0; - - st->odr_pwm = devm_pwm_get(dev, "odr_pwm"); - if (IS_ERR(st->odr_pwm)) - dev_err(&st->spi->dev, "Failed to find ODR PWM\n"); - - ret = devm_add_action_or_reset(dev, ad4134_disable_pwm, st->odr_pwm); - if (ret) - return dev_err_probe(dev, ret, - "Failed to add ODR PWM disable action\n"); - - st->trigger_pwm = devm_pwm_get(dev, "trigger_pwm"); - if (IS_ERR(st->trigger_pwm)) - dev_err(&st->spi->dev, "Failed to find trigger PWM\n"); - - ret = devm_add_action_or_reset(dev, ad4134_disable_pwm, st->trigger_pwm); - if (ret) - return dev_err_probe(dev, ret, - "Failed to add ODR PWM disable action\n"); - - fsleep(3000); - if (!IS_ERR(st->odr_pwm) & !IS_ERR(st->trigger_pwm)) { - ret = _ad4134_set_odr(st, AD4134_ODR_DEFAULT); - if (ret) - return dev_err_probe(dev, ret, "Failed to initialize ODR\n"); - - ret = pwm_enable(st->odr_pwm); - if (ret) - return dev_err_probe(dev, ret, "Failed to enable ODR PWM\n"); - - ret = pwm_enable(st->trigger_pwm); - if (ret) - return dev_err_probe(dev, ret, - "Failed to enable trigger PWM\n"); - } else { - dev_warn(dev, "Failed to find ODR PWM\n"); - } - - return 0; -} static int ad4134_setup(struct ad4134_state *st) { @@ -709,6 +913,7 @@ static int ad4134_setup(struct ad4134_state *st) st->sys_clk_rate = clk_get_rate(clk); if (!st->sys_clk_rate) return dev_err_probe(dev, -EINVAL, "Failed to get SYS clock rate\n"); + st->sys_clk_hz = st->sys_clk_rate; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regulators), st->regulators); @@ -744,9 +949,6 @@ static int ad4134_setup(struct ad4134_state *st) gpiod_set_value_cansleep(reset_gpio, 0); - ret = ad4134_pwm_setup(st); - if (ret) - return ret; ret = regmap_update_bits(st->regmap, AD4134_DATA_PACKET_CONFIG_REG, AD4134_DATA_PACKET_CONFIG_FRAME_MASK, @@ -805,6 +1007,10 @@ static int ad4134_bind(struct device *dev) struct ad4134_state *st = iio_priv(indio_dev); int ret; + ret = ad4134_offload_buffer_setup(indio_dev, st->spi); + if (ret) + return ret; + ret = component_bind_all(dev, st); if (ret) return ret; @@ -913,25 +1119,13 @@ static int ad4134_probe(struct spi_device *spi) "Failed to config ADC frame\n"); } - /* - * Receive buffer needs to be non-zero for the SPI engine master - * to mark the transfer as a read. - */ - st->buf_read_xfer.rx_buf = (void *)-1; - st->buf_read_xfer.len = 1; - /* - * TODO implement multiple scan_type structs so storagebits and - * bits_per_word can be set differently for DMA and non-DMA able cases? - */ - st->buf_read_xfer.bits_per_word = indio_dev->channels->scan_type.realbits + - indio_dev->channels->scan_type.shift; - spi_message_init_with_transfers(&st->buf_read_msg, - &st->buf_read_xfer, 1); - st->regmap = devm_regmap_init_spi(spi, &ad4134_regmap_config); if (IS_ERR(st->regmap)) return PTR_ERR(st->regmap); + /* The HDL is hardconded/configured to read from all 4 DOUT lines. */ + st->num_dout_lines = 4; + ret = ad4134_setup(st); if (ret) return ret; @@ -947,15 +1141,14 @@ static int ad4134_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad4134_info; - ret = devm_iio_dmaengine_buffer_setup(dev, indio_dev, "rx"); - if (ret) { + if (!device_property_present(&st->spi->dev, "adi,spi-engine")) { indio_dev->channels = 0; indio_dev->num_channels = 0; indio_dev->available_scan_masks = 0; return devm_iio_device_register(dev, indio_dev); } - indio_dev->setup_ops = &ad4134_buffer_ops; + indio_dev->setup_ops = &ad4134_offload_buffer_setup_ops; st->spi_engine_fwnode = fwnode_find_reference(fwnode, "adi,spi-engine", 0); if (IS_ERR(st->spi_engine_fwnode)) From 98306d381f90c73f4594c3816373922a849e8a42 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 24 Mar 2026 17:20:33 -0300 Subject: [PATCH 25/75] iio: adc: ad4134: Do offload setup after SPI offload device probe Only setup SPI offloading after having a handle to the device connected to SPI Engine. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index a135dfaa30fd3a..3ce78aee817329 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -1007,11 +1007,11 @@ static int ad4134_bind(struct device *dev) struct ad4134_state *st = iio_priv(indio_dev); int ret; - ret = ad4134_offload_buffer_setup(indio_dev, st->spi); + ret = component_bind_all(dev, st); if (ret) return ret; - ret = component_bind_all(dev, st); + ret = ad4134_offload_buffer_setup(indio_dev, st->spi); if (ret) return ret; From 0099ea728e432b3a85a8c4e8c32b9698ef1ac83b Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 24 Mar 2026 17:22:51 -0300 Subject: [PATCH 26/75] iio: adc: ad4134: Use SPI Engine connected device pointer to config offload Use the pointer to the device connected to SPI Engine to configure SPI offloading. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 3ce78aee817329..2de361a301ebe5 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -589,11 +589,12 @@ static const struct iio_buffer_setup_ops ad4134_offload_buffer_setup_ops = { static int ad4134_spi_offload_setup(struct iio_dev *indio_dev, struct ad4134_state *st) { + struct device *offload_dev = &st->spi_engine->dev; struct device *dev = &st->spi->dev; struct dma_chan *rx_dma; - st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload, + st->offload_trigger = devm_spi_offload_trigger_get(offload_dev, st->offload, SPI_OFFLOAD_TRIGGER_PERIODIC); if (IS_ERR(st->offload_trigger)) return dev_err_probe(dev, PTR_ERR(st->offload_trigger), @@ -601,12 +602,13 @@ static int ad4134_spi_offload_setup(struct iio_dev *indio_dev, st->offload_trigger_config.type = SPI_OFFLOAD_TRIGGER_PERIODIC; - rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(offload_dev, st->offload); if (IS_ERR(rx_dma)) - return dev_err_probe(dev, PTR_ERR(rx_dma), + return dev_err_probe(offload_dev, PTR_ERR(rx_dma), "failed to get offload RX DMA\n"); - return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + return devm_iio_dmaengine_buffer_setup_with_handle(offload_dev, + indio_dev, rx_dma, IIO_BUFFER_DIRECTION_IN); } @@ -627,10 +629,11 @@ static int ad4134_pwm_get(struct ad4134_state *st) static int ad4134_offload_buffer_setup(struct iio_dev *indio_dev, struct spi_device *spi) { struct ad4134_state *st = iio_priv(indio_dev); + struct device *offload_dev = &st->spi_engine->dev; struct device *dev = &spi->dev; int ret; - st->offload = devm_spi_offload_get(dev, spi, &ad4134_offload_config); + st->offload = devm_spi_offload_get(offload_dev, st->spi_engine, &ad4134_offload_config); ret = PTR_ERR_OR_ZERO(st->offload); if (ret && ret != -ENODEV) return dev_err_probe(dev, ret, "failed to get offload\n"); From f4aa5dcabc489a73dcd8d6828614254b00e70c10 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 25 Mar 2026 10:00:12 -0300 Subject: [PATCH 27/75] iio: adc: ad4134: Use SPI offload connected device to optimize messages Use the handle to the device connected to SPI Engine to optimize (i.e. configure for offloading) SPI messages. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 2de361a301ebe5..ffce12504dc8ec 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -545,7 +545,7 @@ static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev) ad4134_prepare_offload_msg(indio_dev); st->msg.offload = st->offload; - ret = spi_optimize_message(st->spi, &st->msg); + ret = spi_optimize_message(st->spi_engine, &st->msg); if (ret) return ret; From 23116846120690fc862129c7a3ada9255a044dfd Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 25 Mar 2026 11:00:22 -0300 Subject: [PATCH 28/75] iio: adc: ad4134: Drop odr_set_freq "odr_set_freq" is not standard IIO ABI and is no longer used for sampling frequency configuration. Thus, the leftover extended attribute might only cause confusion. Drop it. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 107 +++++---------------------------------- 1 file changed, 14 insertions(+), 93 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index ffce12504dc8ec..25d493502529ff 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -143,13 +143,6 @@ static int ad7134_set_dig_fil(struct iio_dev *dev, unsigned int filter); static int ad7134_get_dig_fil(struct iio_dev *dev, const struct iio_chan_spec *chan); -static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - const char *buf, size_t len); -static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, char *buf); static const struct iio_enum ad7134_flt_type_iio_enum = { .items = ad7134_filter_enum, @@ -161,13 +154,6 @@ static const struct iio_enum ad7134_flt_type_iio_enum = { static struct iio_chan_spec_ext_info ad7134_ext_info[] = { IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7134_flt_type_iio_enum), IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL, &ad7134_flt_type_iio_enum), - { - .name = "odr_set_freq", - .read = ad7134_ext_info_read, - .write = ad7134_ext_info_write, - .shared = IIO_SHARED_BY_ALL, - .private = ODR_SET_FREQ, - }, { .name = "ad4134_sync", .write = ad7134_set_sync, @@ -316,29 +302,6 @@ static int ad7134_get_dig_fil(struct iio_dev *dev, return FIELD_GET(AD4134_CHAN_DIG_FILTER_SEL_FRAME_MASK_CH0, readval); } -static ssize_t ad7134_ext_info_read(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, char *buf) -{ - int ret = -EINVAL; - long long val; - struct ad4134_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - - switch (private) { - case ODR_SET_FREQ: - val = st->odr; - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&st->lock); - - return sprintf(buf, "%lld\n", val); -} - static int ad4134_samp_freq_avail[] = { AD4134_ODR_MIN, 1, AD4134_ODR_MAX }; /* @@ -661,61 +624,6 @@ static int ad4134_offload_buffer_setup(struct iio_dev *indio_dev, struct spi_dev return 0; } -static int ad4134_set_odr(struct iio_dev *indio_dev, unsigned int odr) -{ - struct ad4134_state *st = iio_priv(indio_dev); - int ret; - - if (IS_ERR(st->odr_trigger)) - return 0; - - if (IS_ERR(st->offload_trigger)) - return 0; - - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - mutex_lock(&st->lock); - - ret = ad4134_update_conversion_rate(st, odr); - - mutex_unlock(&st->lock); - - iio_device_release_direct_mode(indio_dev); - - return ret; -} - -static ssize_t ad7134_ext_info_write(struct iio_dev *indio_dev, - uintptr_t private, - const struct iio_chan_spec *chan, - const char *buf, size_t len) -{ - int ret = -EINVAL; - long long readin; - struct ad4134_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - - switch (private) { - case ODR_SET_FREQ: - ret = kstrtoll(buf, 10, &readin); - if (ret) - goto out; - readin = clamp_t(long long, readin, 0, 1500000); - ret = ad4134_update_conversion_rate(st, readin); - break; - - default: - ret = -EINVAL; - } -out: - mutex_unlock(&st->lock); - - return ret ? ret : len; -} - static int ad4134_input_gpio(struct gpio_chip *chip, unsigned int offset) { struct ad4134_state *st = gpiochip_get_data(chip); @@ -851,9 +759,22 @@ static int ad4134_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long info) { + struct ad4134_state *st = iio_priv(indio_dev); + int ret; + switch (info) { case IIO_CHAN_INFO_SAMP_FREQ: - return ad4134_set_odr(indio_dev, val); + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + mutex_lock(&st->lock); + ret = ad4134_update_conversion_rate(st, val); + mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); + + return ret; default: return -EINVAL; } From d08542da59ffb0c1935844c7255a464b252d8515 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 25 Mar 2026 11:06:42 -0300 Subject: [PATCH 29/75] iio: adc: ad4134: Provide correct sampling frequency with new offload Output the correct sampling frequency value with the new SPI offload support. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 25d493502529ff..e1b2d106952107 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -730,7 +730,7 @@ static int ad4134_read_raw(struct iio_dev *indio_dev, return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_SAMP_FREQ: mutex_lock(&st->lock); - *val = st->odr; + *val = st->odr_hz * st->num_dout_lines; mutex_unlock(&st->lock); return IIO_VAL_INT; From 18d0cb56cb3d9437f32fa8d9a01b2dec08258fa7 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 25 Mar 2026 12:00:11 -0300 Subject: [PATCH 30/75] iio: adc: ad4134: Fail if no offload device is found Previously, AD4134 driver would cause a kernel oops if no offload capable device was obtained at device probe. Properly error out if SPI offload is not available. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index e1b2d106952107..0ccbcecad2a6fd 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -598,7 +598,7 @@ static int ad4134_offload_buffer_setup(struct iio_dev *indio_dev, struct spi_dev st->offload = devm_spi_offload_get(offload_dev, st->spi_engine, &ad4134_offload_config); ret = PTR_ERR_OR_ZERO(st->offload); - if (ret && ret != -ENODEV) + if (ret) return dev_err_probe(dev, ret, "failed to get offload\n"); From 9715910ae3ee5ae0d6b76f08856a65cf699c4938 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 31 Mar 2026 12:14:28 -0300 Subject: [PATCH 31/75] iio: adc: ad4134: Use same transfer bits per word and size as previous version Use same transfer bits per word and size as previous version. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 0ccbcecad2a6fd..f60a50347cf507 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -490,11 +490,12 @@ const struct attribute_group ad4134_offload_attribute_group = { static void ad4134_prepare_offload_msg(struct iio_dev *indio_dev) { struct ad4134_state *st = iio_priv(indio_dev); + unsigned int bpw = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS)); unsigned int i; for (i = 0; i < AD4134_NUM_CHANNELS; i++) { - st->xfers[i].bits_per_word = AD4134_CHAN_PRECISION_BITS; - st->xfers[i].len = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS)); + st->xfers[i].bits_per_word = bpw; + st->xfers[i].len = bpw / st->num_dout_lines; st->xfers[i].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; } From 5470c7bbcb683d305e0544b009687e7880cfc46e Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 31 Mar 2026 14:02:36 -0300 Subject: [PATCH 32/75] iio: adc: ad4134: Adjust ODR PWM period check No functional change. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index f60a50347cf507..9091abee83182d 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -388,7 +388,11 @@ static int ad4134_update_conversion_rate(struct ad4134_state *st, target += 10; } while (odr_wf.duty_length_ns < odr_high_time_ns); - if (!in_range(odr_wf.period_length_ns, 2 * odr_high_time_ns, UINT_MAX)) + /* + * PWM waveform rounding might also change the wave period. Double check + * the resulting ODR PWM period is valid. + */ + if (odr_wf.period_length_ns < 2 * odr_high_time_ns) return -EINVAL; /* From 05257eecd5fe045c1f9ed912113018314f876d42 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 31 Mar 2026 14:05:29 -0300 Subject: [PATCH 33/75] iio: adc: ad4134: Start ODR PWM optimization with a non-zero duty length Start ODR PWM optimization with a non-zero duty length. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 9091abee83182d..cce3a1484297e4 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -354,7 +354,7 @@ static int ad4134_update_conversion_rate(struct ad4134_state *st, u64 offload_offset_ns; u64 odr_high_time_ns; unsigned int odr_hz; - u64 target = 0; + u64 target = 10; int ret; /* From 6f7fc6133911962bc19c7ac1d4488555b9973293 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 14:37:56 -0300 Subject: [PATCH 34/75] iio: adc: ad4134: Start ODR on device power up and keep it free running Apparently, for AD4134, the ODR signal is not just about the output data rate. According to reports from fellow engineers, AD4134 chip also uses the ODR signal for it's internal operation similarly to an external clock source. Thus, start the ODR input source on device probe and do not disable that after data captures. Also, use ODR as sampling frequency (subject to redesign). This solves the issue of the device not correctly writing to configuration registers during device probe. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 128 ++++++++++++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 27 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index cce3a1484297e4..6865bad625399b 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -340,6 +341,66 @@ static const unsigned long ad4134_offload_scan_masks[] = { 0 }; +static int ad4134_setup_odr(struct ad4134_state *st, unsigned int freq_hz) +{ + struct pwm_waveform odr_wf = { }; + u64 odr_high_time_ns; + unsigned int odr_hz; + u64 target = 10; + int ret; + + dev_info(&st->spi->dev, "%s: Updating conversion rate to %u Hz\n", + __func__, freq_hz); + + /* + * Every ODR pulse causes each of the 4 ADCs within the AD4134 chip to + * take a sample simultaneously. The peripheral then outputs the data + * from all those channels over one, two, or four data output lanes. If + * the controller can fetch data from multiple lanes, the throughput is + * increased proportionally to the number of data lanes in use. + * Conversely, when multiple data lanes are enabled, the requested + * sampling frequency can be reached with slower ODR frequencies. ? + */ + //odr_hz = freq_hz / st->num_dout_lines; + odr_hz = freq_hz; + dev_info(&st->spi->dev, "ODR frequency: %u Hz (DOUT lines: %u)\n", + odr_hz, st->num_dout_lines); + if (odr_hz < AD4134_MIN_ODR_FREQ_HZ || odr_hz > AD4134_MAX_ODR_FREQ_HZ) { + dev_err(&st->spi->dev, "ODR %u Hz out of range [%d, %d]\n", + odr_hz, AD4134_MIN_ODR_FREQ_HZ, AD4134_MAX_ODR_FREQ_HZ); + return -EINVAL; + } + + odr_wf.period_length_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, odr_hz); + /* + * For an arbitrary system clock (fSYSCLK), we have a minimum ODR high + * time of 6/fSYSCLK derived from the device clock and data interface + * timing (with Gated DCLK) specifications. Set the PWM duty cycle to + * keep ODR up for at least that long. If the rounded PWM's value is + * less than the minimum required, increase the target value by 10 and + * attempt to round the waveform again, until the minimum is reached. + */ + odr_high_time_ns = div64_ul(6ULL * NANO, st->sys_clk_hz); + do { + odr_wf.duty_length_ns = target; + ret = pwm_round_waveform_might_sleep(st->odr_trigger, &odr_wf); + if (ret) + return ret; + target += 10; + } while (odr_wf.duty_length_ns < odr_high_time_ns); + + /* + * PWM waveform rounding might also change the wave period. Double check + * the resulting ODR PWM period is valid. + */ + if (odr_wf.period_length_ns < 2 * odr_high_time_ns) + return -EINVAL; + + ret = pwm_set_waveform_might_sleep(st->odr_trigger, &odr_wf, false); + + return 0; +} + static const struct spi_offload_config ad4134_offload_config = { .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | SPI_OFFLOAD_CAP_RX_STREAM_DMA, @@ -366,7 +427,8 @@ static int ad4134_update_conversion_rate(struct ad4134_state *st, * Conversely, when multiple data lanes are enabled, the requested * sampling frequency can be reached with slower ODR frequencies. */ - odr_hz = freq_hz / st->num_dout_lines; + //odr_hz = freq_hz / st->num_dout_lines; + odr_hz = freq_hz; if (odr_hz < AD4134_MIN_ODR_FREQ_HZ || odr_hz > AD4134_MAX_ODR_FREQ_HZ) return -EINVAL; @@ -388,6 +450,10 @@ static int ad4134_update_conversion_rate(struct ad4134_state *st, target += 10; } while (odr_wf.duty_length_ns < odr_high_time_ns); + ret = pwm_set_waveform_might_sleep(st->odr_trigger, &odr_wf, false); + if (ret) + return -EINVAL; + /* * PWM waveform rounding might also change the wave period. Double check * the resulting ODR PWM period is valid. @@ -398,10 +464,11 @@ static int ad4134_update_conversion_rate(struct ad4134_state *st, /* * The controller fetches one sample per active lane each time the * offload module is triggered. If multiple data lanes are enabled, the - * offload trigger frequency can be proportionally slower. + * offload trigger frequency can be proportionally slower. ? */ offload_period_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, - odr_hz * st->num_dout_lines); +// odr_hz * st->num_dout_lines); + odr_hz); config->periodic.frequency_hz = DIV_ROUND_UP_ULL(NSEC_PER_SEC, offload_period_ns); @@ -439,7 +506,8 @@ static ssize_t sampling_frequency_show(struct device *dev, * If the controller can fetch data from multiple lanes, the throughput * is increased proportionally to the number of data lanes in use. */ - return sysfs_emit(buf, "%u\n", st->odr_hz * st->num_dout_lines); + //return sysfs_emit(buf, "%u\n", st->odr_hz * st->num_dout_lines); + return sysfs_emit(buf, "%u\n", st->odr_hz); } static ssize_t sampling_frequency_store(struct device *dev, @@ -517,19 +585,13 @@ static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev) if (ret) return ret; - ret = pwm_set_waveform_might_sleep(st->odr_trigger, &st->odr_wf, false); - if (ret) - goto out_unoptimize; - ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, &st->offload_trigger_config); if (ret) - goto out_pwm_disable; + goto out_unoptimize; return 0; -out_pwm_disable: - pwm_disable(st->odr_trigger); out_unoptimize: spi_unoptimize_message(&st->msg); @@ -542,7 +604,6 @@ static int ad4134_offload_buffer_predisable(struct iio_dev *indio_dev) spi_offload_trigger_disable(st->offload, st->offload_trigger); - pwm_disable(st->odr_trigger); spi_unoptimize_message(&st->msg); @@ -589,7 +650,6 @@ static int ad4134_pwm_get(struct ad4134_state *st) return dev_err_probe(dev, PTR_ERR(st->odr_trigger), "failed to get ODR PWM\n"); - pwm_disable(st->odr_trigger); return 0; } @@ -612,19 +672,6 @@ static int ad4134_offload_buffer_setup(struct iio_dev *indio_dev, struct spi_dev return dev_err_probe(dev, ret, "failed to setup SPI offload\n"); - ret = ad4134_pwm_get(st); - if (ret) - return dev_err_probe(dev, ret, "failed to get PWM: %d\n", ret); - - /* - * Start with a slower sampling rate so there is some room for - * adjusting the sampling frequency without hitting the maximum - * conversion rate. - */ - st->odr_hz = AD4134_MAX_ODR_FREQ_HZ >> 4; - ret = ad4134_update_conversion_rate(st, st->odr_hz); - if (ret) - return dev_err_probe(dev, ret, "failed to set offload samp freq\n"); return 0; } @@ -735,7 +782,7 @@ static int ad4134_read_raw(struct iio_dev *indio_dev, return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_SAMP_FREQ: mutex_lock(&st->lock); - *val = st->odr_hz * st->num_dout_lines; + *val = st->odr_hz; mutex_unlock(&st->lock); return IIO_VAL_INT; @@ -878,6 +925,29 @@ static int ad4134_setup(struct ad4134_state *st) gpiod_set_value_cansleep(reset_gpio, 0); + if (device_property_present(&st->spi->dev, "pwms")) { + ret = ad4134_pwm_get(st); + if (ret) + return dev_err_probe(dev, ret, "failed to get PWM: %d\n", ret); + + dev_info(dev, "PWM obtained successfully\n"); + + /* + * Start with a slower sampling rate so there is some room for + * adjusting the sampling frequency without hitting the maximum + * conversion rate. + */ + st->odr_hz = AD4134_MAX_ODR_FREQ_HZ >> 4; + dev_info(dev, "Setting initial ODR frequency to %u Hz\n", st->odr_hz); + //ret = ad4134_update_conversion_rate(st, st->odr_hz); + ret = ad4134_setup_odr(st, st->odr_hz); + if (ret) + return dev_err_probe(dev, ret, "failed to set odr freq\n"); + + dev_info(&st->spi->dev, "wait\n"); + fsleep(MEGA); /* 10^6 microsecs == 1s settling time so PPL lock */ + } + ret = regmap_update_bits(st->regmap, AD4134_DATA_PACKET_CONFIG_REG, AD4134_DATA_PACKET_CONFIG_FRAME_MASK, @@ -944,6 +1014,10 @@ static int ad4134_bind(struct device *dev) if (ret) return ret; + ret = ad4134_update_conversion_rate(st, st->odr_hz); + if (ret) + return dev_err_probe(dev, ret, "failed to set sampling freq\n"); + return iio_device_register(indio_dev); } From 48f10dda1d913b234a4c3e6fc3fc5b36d40cc241 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 14:01:51 -0300 Subject: [PATCH 35/75] iio: adc: ad4134: Set proper IIO buffer shift and endianness properites The current support is intended to work with SPI Engine offloading and thus data will be pushed to memory in CPU endianess, requiring no shifting. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 6865bad625399b..2233206ed7da91 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -129,7 +129,8 @@ static const char * const ad7134_filter_enum[] = { .sign = 's', \ .realbits = (_realbits), \ .storagebits = 32, \ - .shift = ((_storebits) - (_realbits)) \ + .shift = 0, \ + .endianness = IIO_CPU, \ }, \ .ext_info = _ext_info, \ } From 183847f1fd1f57b306e14870df27e8e9c88f63a5 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 16:37:25 -0300 Subject: [PATCH 36/75] iio: adc: ad4134: Adjust SPI transfer to multi-lane data capture Update the SPI transfer configurations to guater data from multiple input lines with multi-lane support. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 2233206ed7da91..d454dc9814e6f3 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -211,7 +211,7 @@ struct ad4134_state { unsigned long sys_clk_hz; - struct spi_transfer xfers[AD4134_NUM_CHANNELS]; + struct spi_transfer xfers; struct spi_message msg; struct spi_offload *offload; @@ -563,16 +563,33 @@ const struct attribute_group ad4134_offload_attribute_group = { static void ad4134_prepare_offload_msg(struct iio_dev *indio_dev) { struct ad4134_state *st = iio_priv(indio_dev); - unsigned int bpw = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS)); - unsigned int i; + unsigned int base_len = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS)); + unsigned int bpw; - for (i = 0; i < AD4134_NUM_CHANNELS; i++) { - st->xfers[i].bits_per_word = bpw; - st->xfers[i].len = bpw / st->num_dout_lines; - st->xfers[i].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + switch (st->output_frame) { + case 0: + bpw = 16; + break; + case 1: + case 2: + bpw = 24; + break; + case 3: + bpw = 32; + break; + default: + dev_err(&st->spi->dev, "invalid adi,adc-frame: %d\n", st->output_frame); + return; } - spi_message_init_with_transfers(&st->msg, st->xfers, AD4134_NUM_CHANNELS); + st->xfers.bits_per_word = bpw; + st->xfers.len = base_len * st->num_dout_lines; + if (st->num_dout_lines > 1) + st->xfers.multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; + + st->xfers.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + + spi_message_init_with_transfers(&st->msg, &st->xfers, 1); } static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev) From 8969bb35c27a09e78c18db1e42d9563a6f9df78f Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 16:57:35 -0300 Subject: [PATCH 37/75] iio: adc: ad4134: Adjust SPI transfer params to cope with 2 devices Adjust SPI offload transfer parameters to store data from 2 devices when supporting AD7134/AD4134 double-device setup. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index d454dc9814e6f3..593c2fe5f461aa 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -239,6 +239,7 @@ struct ad4134_state { int refin_mv; int output_frame; u8 num_dout_lines; + bool ad4134_duo; }; @@ -564,6 +565,7 @@ static void ad4134_prepare_offload_msg(struct iio_dev *indio_dev) { struct ad4134_state *st = iio_priv(indio_dev); unsigned int base_len = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS)); + unsigned int num_devices; unsigned int bpw; switch (st->output_frame) { @@ -581,9 +583,10 @@ static void ad4134_prepare_offload_msg(struct iio_dev *indio_dev) dev_err(&st->spi->dev, "invalid adi,adc-frame: %d\n", st->output_frame); return; } + num_devices = st->ad4134_duo ? 2 : 1; st->xfers.bits_per_word = bpw; - st->xfers.len = base_len * st->num_dout_lines; + st->xfers.len = base_len * st->num_dout_lines * num_devices; if (st->num_dout_lines > 1) st->xfers.multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; @@ -1080,6 +1083,7 @@ static int ad4134_probe(struct spi_device *spi) st->regulators[AD4134_REFIN_REGULATOR].supply = "refin"; ad4134_duo = ad4134_get_ADC_count(st) == 2; + st->ad4134_duo = ad4134_duo; st->output_frame = AD4134_DATA_PACKET_24BIT_FRAME; ret = device_property_match_property_string(dev, "adi,adc-frame", From 2e217de0b60f4f1d61c15f9df9fd1a3de0f671c1 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 17:12:59 -0300 Subject: [PATCH 38/75] iio: adc: ad4134: Extract synchronization procedure into own function Extract the multiple chip synchronization procedure into a separate function for reuse. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 593c2fe5f461aa..81ddb0c13e6c5f 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -249,9 +249,7 @@ static ssize_t ad7134_get_sync(struct iio_dev *indio_dev, uintptr_t private, return sprintf(buf, "enable\n"); } -static ssize_t ad7134_set_sync(struct iio_dev *indio_dev, uintptr_t private, - const struct iio_chan_spec *chan, - const char *buf, size_t len) +static int ad7134_sync(struct iio_dev *indio_dev) { struct ad4134_state *st = iio_priv(indio_dev); int ret; @@ -262,8 +260,20 @@ static ssize_t ad7134_set_sync(struct iio_dev *indio_dev, uintptr_t private, (AD4134_IF_CONFIG_B_RESET | AD4134_IF_CONFIG_B_SINGLE_INSTR)); if (ret) return ret; + gpiod_set_value_cansleep(st->cs_gpio, 0); + return 0; +} + +static ssize_t ad7134_set_sync(struct iio_dev *indio_dev, uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + int ret; + + ret = ad7134_sync(indio_dev); + return ret ? ret : len; } From 3c6e0452782f965f6a85de6ecffb41dfe9e1ebcc Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 17:15:50 -0300 Subject: [PATCH 39/75] iio: adc: ad4134: Do automatic multi-device synchronization when applicable Automatically run the multi-device synchronization procedure when supporting AD7134/AD4134 double-device setup. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 81ddb0c13e6c5f..10fd8f500285b5 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -616,6 +616,15 @@ static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev) if (ret) return ret; + if (st->ad4134_duo) { + ret = ad7134_sync(indio_dev); + if (ret) + { + dev_err(&st->spi->dev, "ad7134_sync failed: %d\n", ret); + return ret; + } + } + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, &st->offload_trigger_config); if (ret) From e46a4553272ff3784ba55cbca2156ee473fcd09a Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Mon, 11 May 2026 11:11:14 -0300 Subject: [PATCH 40/75] iio: adc: ad4143: Drop automatic multi-device synchronization Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 10fd8f500285b5..81ddb0c13e6c5f 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -616,15 +616,6 @@ static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev) if (ret) return ret; - if (st->ad4134_duo) { - ret = ad7134_sync(indio_dev); - if (ret) - { - dev_err(&st->spi->dev, "ad7134_sync failed: %d\n", ret); - return ret; - } - } - ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, &st->offload_trigger_config); if (ret) From 1ba7e131b7adc08b2be856d839a716c0e6733e5b Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 10:21:59 -0300 Subject: [PATCH 41/75] iio: adc: ad4134: Add author This driver got many updates it now looks very different from what it was before. Add second author to the registered module authors. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 81ddb0c13e6c5f..4b8ba052631ecc 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -1300,6 +1300,7 @@ static void __exit ad4134_exit(void) module_exit(ad4134_exit); MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_AUTHOR("Marcelo Schmitt "); MODULE_DESCRIPTION("Analog Devices AD4134 SPI driver"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER); From 95522b892fa2ee66115ec18270dd4b39ef83b1e3 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 11:56:15 -0300 Subject: [PATCH 42/75] iio: adc: ad4134: Add soft reset device attribute Add a soft reset device attribute to speed up tests. Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 4b8ba052631ecc..1a339e0f0d8eae 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -43,6 +43,9 @@ #define AD4134_NAME "ad4134" +#define AD4134_IF_CONFIG_A_REG 0x0 +#define AD4134_IF_CONFIG_A_RESET_MASK (BIT(7) | BIT(0)) + #define AD4134_IF_CONFIG_B_REG 0x01 #define AD4134_IF_CONFIG_B_SINGLE_INSTR BIT(7) #define AD4134_IF_CONFIG_B_MASTER_SLAVE_RD_CTRL BIT(5) @@ -561,7 +564,31 @@ static ssize_t sampling_frequency_available_show(struct device *dev, static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0); +static ssize_t soft_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad4134_state *st = iio_priv(indio_dev); + unsigned int val; + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + ret = regmap_update_bits(st->regmap, AD4134_IF_CONFIG_A_REG, + AD4134_IF_CONFIG_A_RESET_MASK, + AD4134_IF_CONFIG_A_RESET_MASK); + +out_store: + iio_device_release_direct(indio_dev); + return ret ?: len; +} + +static IIO_DEVICE_ATTR_WO(soft_reset, 0); + static struct attribute *ad4134_offload_attributes[] = { + &iio_dev_attr_soft_reset.dev_attr.attr, /* Can be provided without offload */ &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr, NULL, From 7a2ae60380062cc34f5c17c9f1d5555535c45bfa Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 12:08:06 -0300 Subject: [PATCH 43/75] iio: adc: ad4134: [HACK] Set duo device GPIO for soft reset Signed-off-by: Marcelo Schmitt --- drivers/iio/adc/ad4134.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c index 1a339e0f0d8eae..2641e015adf5d6 100644 --- a/drivers/iio/adc/ad4134.c +++ b/drivers/iio/adc/ad4134.c @@ -576,10 +576,13 @@ static ssize_t soft_reset_store(struct device *dev, if (!iio_device_claim_direct(indio_dev)) return -EBUSY; + gpiod_set_value_cansleep(st->cs_gpio, 1); ret = regmap_update_bits(st->regmap, AD4134_IF_CONFIG_A_REG, AD4134_IF_CONFIG_A_RESET_MASK, AD4134_IF_CONFIG_A_RESET_MASK); + gpiod_set_value_cansleep(st->cs_gpio, 0); + out_store: iio_device_release_direct(indio_dev); return ret ?: len; From d5d8708f6857f48cf9458bf13937319e5cb156b8 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 15:18:03 -0300 Subject: [PATCH 44/75] ARM: dts: Add device tree for AD7134(-24) on ZedBoard Add device tree for AD7134 (with 24-bit precision) on ZedBoard. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts new file mode 100644 index 00000000000000..d4101a644eb8c3 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include + +#include "zynq-zed.dtsi" +#include "zynq-zed-adv7511.dtsi" + +/ { + avdd5: regulator-avdd5 { + compatible = "regulator-fixed"; + regulator-name = "avdd5"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + avdd1v8: regulator-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "avdd1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + iovdd: regulator-iovdd { + compatible = "regulator-fixed"; + regulator-name = "iovdd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + refin: regulator-refin { + compatible = "regulator-fixed"; + regulator-name = "refin"; + regulator-min-microvolt = <4096000>; + regulator-max-microvolt = <4096000>; + regulator-always-on; + }; + + clocks { + cnv_ext_clk: ext-clk { + #clock-cells = <0x0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + clock-output-names = "cnv_ext_clk"; + }; + }; +}; + +&fpga_axi { + rx_dma: rx-dmac@44a30000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x44a30000 0x1000>; + #dma-cells = <1>; + interrupt-parent = <&intc>; + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15>; + + adi,channels { + #size-cells = <0>; + #address-cells = <1>; + + dma-channel@0 { + reg = <0>; + adi,source-bus-width = <128>; + adi,source-bus-type = <1>; + adi,destination-bus-width = <64>; + adi,destination-bus-type = <0>; + }; + }; + }; + + axi_spi_engine_0: spi@44a00000 { + compatible = "adi,axi-spi-engine-1.00.a"; + reg = <0x44a00000 0x10000>; + interrupt-parent = <&intc>; + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15 &spi_clk>; + clock-names = "s_axi_aclk", "spi_clk"; + num-cs = <1>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + ad4134_spi_engine: spi_engine@0 { + compatible = "adi,ad4134-spi-engine"; + reg = <0>; + + spi-max-frequency = <50000000>; + + spi-cpha; + }; + }; + + ad4134_odr_generator: odr_generator@44b00000 { + compatible = "adi,axi-pwmgen"; + reg = <0x44b00000 0x10000>; + #pwm-cells = <2>; + clocks = <&cnv_ext_clk>; + //clocks = <&spi_clk>; + //clocks = <&clkc 15>; + }; + + spi_clk: axi_clkgen@44b10000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x44b10000 0x10000>; + #clock-cells = <0>; + clocks = <&clkc 15>, <&clkc 15>; + clock-names = "s_axi_aclk", "clkin1"; + clock-output-names = "spi_clk"; + }; +}; + +&spi0 { + status = "okay"; + + ad4134_0: adc_0@0 { + compatible = "adi,ad4134"; + reg = <0>; + + spi-max-frequency = <10000000>; + + reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>; + cs-gpios = <&gpio0 104 GPIO_ACTIVE_HIGH>; + + clocks = <&cnv_ext_clk>; + clock-names = "cnv_ext_clk"; + + dmas = <&rx_dma 0>; + dma-names = "rx"; + + pwms = <&ad4134_odr_generator 0 0 + &ad4134_odr_generator 1 0>; + pwm-names = "trigger_pwm","odr_pwm"; + + avdd5-supply = <&avdd5>; + avdd1v8-supply = <&avdd1v8>; + iovdd-supply = <&iovdd>; + refin-supply = <&refin>; + + adi,spi-engine = <&ad4134_spi_engine>; + adi,adc-frame = "24-bit"; + }; + + ad4134_1: adc_1@1 { + compatible = "adi,ad4134"; + + reg = <1>; + + spi-max-frequency = <10000000>; + + reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>; + + clocks = <&cnv_ext_clk>; + clock-names = "cnv_ext_clk"; + + avdd5-supply = <&avdd5>; + avdd1v8-supply = <&avdd1v8>; + iovdd-supply = <&iovdd>; + refin-supply = <&refin>; + adi,adc-frame = "24-bit"; + }; +}; From 2d61418f31585f01a5ff0fc08725094491f67432 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 15:23:20 -0300 Subject: [PATCH 45/75] ARM: dts: Add device tree for AD7134(-24CRC) on ZedBoard Add device tree for AD7134 (with 24-bit precision and CRC check) on ZedBoard. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- .../xilinx/zynq-zed-adv7511-ad7134-24CRC.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24CRC.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24CRC.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24CRC.dts new file mode 100644 index 00000000000000..c7758208861ede --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24CRC.dts @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include "zynq-zed-adv7511-ad7134-24.dts" + +&spi0 { + status = "okay"; + + ad4134_0: adc_0@0 { + adi,adc-frame = "24-bit+CRC"; + }; + + ad4134_1: adc_1@1 { + adi,adc-frame = "24-bit+CRC"; + }; +}; From 9df36558677b6b1b1eac2a44c2f909d05b17906a Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 15:24:16 -0300 Subject: [PATCH 46/75] ARM: dts: Add device tree for AD7134(-16) on ZedBoard Add device tree for AD7134 (with 16-bit precision) on ZedBoard. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-ad7134-16.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16.dts new file mode 100644 index 00000000000000..92ce2e66134e6e --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16.dts @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include "zynq-zed-adv7511-ad7134-24.dts" + +&spi0 { + status = "okay"; + + ad4134_0: adc_0@0 { + adi,adc-frame = "16-bit"; + }; + + ad4134_1: adc_1@1 { + adi,adc-frame = "16-bit"; + }; +}; From 9dfaf08bf16abe8f3f0699049e121175d84bd617 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 15:24:41 -0300 Subject: [PATCH 47/75] ARM: dts: Add device tree for AD7134(-16CRC) on ZedBoard Add device tree for AD7134 (with 16-bit precision and CRC check) on ZedBoard. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- .../xilinx/zynq-zed-adv7511-ad7134-16CRC.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16CRC.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16CRC.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16CRC.dts new file mode 100644 index 00000000000000..98279e5de2b8a0 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-16CRC.dts @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include "zynq-zed-adv7511-ad7134-24.dts" + +&spi0 { + status = "okay"; + + ad4134_0: adc_0@0 { + adi,adc-frame = "16-bit+CRC"; + }; + + ad4134_1: adc_1@1 { + adi,adc-frame = "16-bit+CRC"; + }; +}; From 3eaef3cde353dd8de97283b1db0a7968141301aa Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 15:25:20 -0300 Subject: [PATCH 48/75] ARM: dts: Add device tree for the CN0561 project on ZedBoard Add device tree for the CN0561 project on ZedBoard. The featured ADC is AD7134. Signed-off-by: Ioan-daniel Pop Co-developed-by: Marcelo Schmitt Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-cn0561-24.dts | 207 ++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts new file mode 100644 index 00000000000000..a0c86b57ca0048 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include + +#include "zynq-zed.dtsi" +#include "zynq-zed-adv7511.dtsi" + +/ { + avdd5: regulator-avdd5 { + compatible = "regulator-fixed"; + regulator-name = "avdd5"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + avdd1v8: regulator-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "avdd1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + iovdd: regulator-iovdd { + compatible = "regulator-fixed"; + regulator-name = "iovdd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + refin: regulator-refin { + compatible = "regulator-fixed"; + regulator-name = "refin"; + regulator-min-microvolt = <4096000>; + regulator-max-microvolt = <4096000>; + regulator-always-on; + }; + + clocks { + cnv_ext_clk: ext-clk { + #clock-cells = <0x0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + clock-output-names = "cnv_ext_clk"; + }; + }; + + ad4134_control@0 { + compatible = "adi,one-bit-adc-dac"; + #address-cells = <1>; + #size-cells = <0>; + + out-gpios = <&ad4134_0 0 0>, <&ad4134_0 1 0>, <&ad4134_0 2 0>, <&ad4134_0 3 0>, + <&ad4134_0 4 0>, <&ad4134_0 5 0>, <&ad4134_0 6 0>, <&ad4134_0 7 0>; + + label = "ad4134"; + + channel@0 { + reg = <0>; + label = "GPIO0"; + }; + + channel@1 { + reg = <1>; + label = "GPIO1"; + }; + + channel@2 { + reg = <2>; + label = "GPIO2"; + }; + + channel@3 { + reg = <3>; + label = "GPIO3"; + }; + + channel@4 { + reg = <4>; + label = "GPIO4"; + }; + + channel@5 { + reg = <5>; + label = "GPIO5"; + }; + + channel@6 { + reg = <6>; + label = "GPIO6"; + }; + + channel@7 { + reg = <7>; + label = "GPIO7"; + }; + }; +}; + +&fpga_axi { + rx_dma: rx-dmac@44a30000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x44a30000 0x1000>; + #dma-cells = <1>; + interrupt-parent = <&intc>; + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15>; + + adi,channels { + #size-cells = <0>; + #address-cells = <1>; + + dma-channel@0 { + reg = <0>; + adi,source-bus-width = <128>; + adi,source-bus-type = <1>; + adi,destination-bus-width = <64>; + adi,destination-bus-type = <0>; + }; + }; + }; + + axi_spi_engine_0: spi@44a00000 { + compatible = "adi,axi-spi-engine-1.00.a"; + reg = <0x44a00000 0x10000>; + interrupt-parent = <&intc>; + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15 &spi_clk>; + clock-names = "s_axi_aclk", "spi_clk"; + num-cs = <1>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + ad4134_spi_engine: spi_engine@0 { + compatible = "adi,ad4134-spi-engine"; + reg = <0>; + + spi-max-frequency = <50000000>; + + spi-cpha; + }; + }; + + ad4134_odr_generator: odr_generator@44b00000 { + compatible = "adi,axi-pwmgen"; + reg = <0x44b00000 0x10000>; + #pwm-cells = <2>; + clocks = <&cnv_ext_clk>; + }; + + spi_clk: axi_clkgen@44b10000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x44b10000 0x10000>; + #clock-cells = <0>; + clocks = <&clkc 15>, <&clkc 15>; + clock-names = "s_axi_aclk", "clkin1"; + clock-output-names = "spi_clk"; + }; +}; + +&spi0 { + status = "okay"; + + ad4134_0: adc_0@0 { + compatible = "adi,ad4134"; + reg = <0>; + + spi-max-frequency = <10000000>; + + reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>; + gpio-cs-gpios = <&gpio0 104 GPIO_ACTIVE_HIGH>; + + clocks = <&cnv_ext_clk>; + clock-names = "cnv_ext_clk"; + + dmas = <&rx_dma 0>; + dma-names = "rx"; + + pwms = <&ad4134_odr_generator 0 0 + &ad4134_odr_generator 1 0>; + pwm-names = "trigger_pwm","odr_pwm"; + + avdd5-supply = <&avdd5>; + avdd1v8-supply = <&avdd1v8>; + iovdd-supply = <&iovdd>; + refin-supply = <&refin>; + + adi,spi-engine = <&ad4134_spi_engine>; + adi,adc-frame = "24-bit"; + + gpio-controller; + #gpio-cells = <2>; + }; +}; From 283937770916cb7197f23f7e9be17d1cb683f52f Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 10 Jan 2025 09:15:22 -0300 Subject: [PATCH 49/75] ARM: dts: zynq-zed-adv7511-ad4134: Add adi,adc-frame value for single AD4134 setup Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index 429bcfca0d9d57..20a149408af71b 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -130,5 +130,6 @@ refin-supply = <&refin>; adi,spi-engine = <&ad4134_spi_engine>; + adi,adc-frame = "24-bit"; }; }; From 9968a64472469f973b91fc54acbdc63e170f49e3 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 17 Jan 2025 10:57:56 -0300 Subject: [PATCH 50/75] ARM: dts: zynq-zed-adv7511-ad4134: Update to new clock name With the driver updates to support dual AD7134 setup, the clock phandle and name have been changed. Update AD4134 dts clock phandle and name to match the names used in AD7134 dts and provide the names the driver expects. Signed-off-by: Marcelo Schmitt --- .../boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index 20a149408af71b..26c171ee940d42 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -48,10 +48,13 @@ regulator-always-on; }; - sys_clk: sys-clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <48000000>; + clocks { + cnv_ext_clk: ext-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "cnv_ext_clk"; + }; }; }; @@ -91,7 +94,7 @@ compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; #pwm-cells = <2>; - clocks = <&clkc 15>, <&spi_clk>; + clocks = <&cnv_ext_clk 15>, <&spi_clk>; clock-names = "axi", "ext"; }; @@ -115,8 +118,8 @@ reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>; - clocks = <&sys_clk>; - clock-names = "sys_clk"; + clocks = <&cnv_ext_clk>; + clock-names = "cnv_ext_clk"; dmas = <&rx_dma 0>; dma-names = "rx"; From 6815f439019fda9c3a3fb22c4fd83b8528ce5ed9 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 17 Jan 2025 11:03:19 -0300 Subject: [PATCH 51/75] ARM: dts: zynq-zed-adv7511-ad4134: Use trigger_pwm The updates to ad4134 driver have added a requirement on a PWM which is used for AD7134 projects (single and duo device setups). The ad4134_fmc HDL project seems to provide/set the PWM trigger too so add that to the dts for AD4134. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index 26c171ee940d42..586132883006fb 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -124,8 +124,9 @@ dmas = <&rx_dma 0>; dma-names = "rx"; - pwms = <&ad4134_odr_generator 0 0>; - pwm-names = "odr_pwm"; + pwms = <&ad4134_odr_generator 0 0 + &ad4134_odr_generator 1 0>; + pwm-names = "trigger_pwm","odr_pwm"; avdd5-supply = <&avdd5>; avdd1v8-supply = <&avdd1v8>; From 2e0f38940eaec8ec724bdf771a05af94a29a2433 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Jan 2025 16:31:08 -0300 Subject: [PATCH 52/75] ARM: dts: zynq-zed-adv7511-ad4134: Set system base clock to 100 MHz Set cnv_ext_clk (which is used as system clock) to 100 MHz as documented in AD4134-FMC HDL project page [1]. 48 MHz clock lead to insuficient trigger_pwm phase value which, among other things, caused ODR and DCLK signal to not be synchronized resulting in incorrect data read from the ADC. [1]: https://analogdevicesinc.github.io/hdl/projects/ad4134_fmc/index.html Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index 586132883006fb..d03c3c874af408 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -52,7 +52,7 @@ cnv_ext_clk: ext-clk { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <48000000>; + clock-frequency = <100000000>; clock-output-names = "cnv_ext_clk"; }; }; From c37500746a5f0c3ba85451b30b6bf65940bcc0da Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Jan 2025 17:02:43 -0300 Subject: [PATCH 53/75] ARM: dts: zynq-zed-adv7511-ad4134: Adjust spi-max-frequency With faster system clock, increase SPI data clock rate (both SPI Engine and ADC) to achieve faster sample rates. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index d03c3c874af408..5221b1bf3c5008 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -84,7 +84,7 @@ compatible = "adi,ad4134-spi-engine"; reg = <0>; - spi-max-frequency = <48000000>; + spi-max-frequency = <50000000>; spi-cpha; }; @@ -114,7 +114,7 @@ compatible = "adi,ad4134"; reg = <0>; - spi-max-frequency = <1000000>; + spi-max-frequency = <10000000>; reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>; From 79aba2ecfacdea9a39141203e2e36a29e0b48085 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 12 Feb 2025 18:40:02 -0300 Subject: [PATCH 54/75] ARM: dts: zynq-zed-adv7511-ad4134: Add output name to axi_clkgen Add clock output name to AXI clock generator node so the whole dts becomes equal to zynq-zed-adv7511-ad4134-24.dts in dev_ad4134 branch which was said to work for AD4134 single device setup. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts index 5221b1bf3c5008..7b56e77ae74d05 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -104,6 +104,7 @@ #clock-cells = <0>; clocks = <&clkc 15>, <&clkc 15>; clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "clkin1", "spi_clk"; }; }; From cdb499c294883bbdcff9dd712cf4ec529d2a2ee5 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Mon, 17 Feb 2025 08:59:50 -0300 Subject: [PATCH 55/75] ARM: dts: Rename AD4134 dts to specify precision bits Add precision bits to AD4134 dts name to better distinguish it from different AD4134 dts that are going to be added in follow up patches. Signed-off-by: Marcelo Schmitt --- ...zynq-zed-adv7511-ad4134.dts => zynq-zed-adv7511-ad4134-24.dts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename arch/arm/boot/dts/xilinx/{zynq-zed-adv7511-ad4134.dts => zynq-zed-adv7511-ad4134-24.dts} (100%) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts similarity index 100% rename from arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts rename to arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts From 7c98634fb1d89699eab71200eada40b88ab4cb34 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Mon, 17 Feb 2025 09:27:50 -0300 Subject: [PATCH 56/75] ARM: dts: Add AD4134-16, AD4134-16CRC, and AD4134-24CRC Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-ad4134-16.dts | 21 +++++++++++++++++++ .../xilinx/zynq-zed-adv7511-ad4134-16CRC.dts | 21 +++++++++++++++++++ .../xilinx/zynq-zed-adv7511-ad4134-24CRC.dts | 21 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16.dts create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16CRC.dts create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24CRC.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16.dts new file mode 100644 index 00000000000000..3b0d1b2f8031fc --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include "zynq-zed-adv7511-ad4134-24.dts" + +&spi0 { + status = "okay"; + + ad4134: adc@0 { + adi,adc-frame = "16-bit"; + }; +}; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16CRC.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16CRC.dts new file mode 100644 index 00000000000000..d9227436e9204d --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-16CRC.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include "zynq-zed-adv7511-ad4134-24.dts" + +&spi0 { + status = "okay"; + + ad4134: adc@0 { + adi,adc-frame = "16-bit+CRC"; + }; +}; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24CRC.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24CRC.dts new file mode 100644 index 00000000000000..d5321e12b9d10f --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24CRC.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD7134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +/dts-v1/; + +#include "zynq-zed-adv7511-ad4134-24.dts" + +&spi0 { + status = "okay"; + + ad4134: adc@0 { + adi,adc-frame = "24-bit+CRC"; + }; +}; From 17824b4eca63753cbf3a67e935e5934b6e738f4f Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 17 Mar 2026 14:10:00 -0300 Subject: [PATCH 57/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Use offload trigger arm: dts [SQUASH] offload Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index 7b56e77ae74d05..203062489d7346 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -48,6 +48,12 @@ regulator-always-on; }; + trigger_pwm: adc-pwm-trigger { + compatible = "pwm-trigger"; + #trigger-source-cells = <0>; + pwms = <&ad4134_odr_generator 0 1000000 0>; + }; + clocks { cnv_ext_clk: ext-clk { compatible = "fixed-clock"; @@ -75,8 +81,9 @@ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clkc 15 &spi_clk>; clock-names = "s_axi_aclk", "spi_clk"; - num-cs = <1>; - + dmas = <&rx_dma 0>; + dma-names = "offload0-rx"; + trigger-sources = <&trigger_pwm>; #address-cells = <0x1>; #size-cells = <0x0>; @@ -122,12 +129,8 @@ clocks = <&cnv_ext_clk>; clock-names = "cnv_ext_clk"; - dmas = <&rx_dma 0>; - dma-names = "rx"; - - pwms = <&ad4134_odr_generator 0 0 - &ad4134_odr_generator 1 0>; - pwm-names = "trigger_pwm","odr_pwm"; + pwm-names = "odr"; + pwms = <&ad4134_odr_generator 1 1000000 0>; avdd5-supply = <&avdd5>; avdd1v8-supply = <&avdd1v8>; From 10a683e818539d00555f80e431fd8d3b4ef3d4cd Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 17 Mar 2026 14:35:40 -0300 Subject: [PATCH 58/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Fix PWM clock cells Fix clock phandles used by ODR PWM device node. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index 203062489d7346..e3b13c0ccfed29 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -101,7 +101,7 @@ compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; #pwm-cells = <2>; - clocks = <&cnv_ext_clk 15>, <&spi_clk>; + clocks = <&clkc 15>, <&cnv_ext_clk>; clock-names = "axi", "ext"; }; From 733db439d55f00125842ac79af46071854964ffc Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 09:22:03 -0300 Subject: [PATCH 59/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Use current/updated SPI Engine Don't use the deprecated legacy SPI Engine anymore. Use the new/updated one instead. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index e3b13c0ccfed29..999cf187b64f2c 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -75,7 +75,7 @@ }; axi_spi_engine_0: spi@44a00000 { - compatible = "adi,legacy-axi-spi-engine-1.00.a"; + compatible = "adi,axi-spi-engine-1.00.a"; reg = <0x44a00000 0x10000>; interrupt-parent = <&intc>; interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; From 186622526735ae2faa41295d54358a3051f2aac9 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 10:21:40 -0300 Subject: [PATCH 60/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Fix PWM clock cells Bump PWM Generator to version 2. Fix clock phandles used by ODR PWM device node. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index d4101a644eb8c3..d5d9419de16ad6 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -104,12 +104,11 @@ }; ad4134_odr_generator: odr_generator@44b00000 { - compatible = "adi,axi-pwmgen"; + compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; #pwm-cells = <2>; - clocks = <&cnv_ext_clk>; - //clocks = <&spi_clk>; - //clocks = <&clkc 15>; + clocks = <&clkc 15>, <&cnv_ext_clk>; + clock-names = "axi", "ext"; }; spi_clk: axi_clkgen@44b10000 { From 807d8f2198998be1af32904d645191e572f8bf11 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 10:30:36 -0300 Subject: [PATCH 61/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Use offload trigger arm: dts [SQUASH] ad7134 offload Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index d5d9419de16ad6..9f971914d3ed5c 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -48,6 +48,12 @@ regulator-always-on; }; + trigger_pwm: adc-pwm-trigger { + compatible = "pwm-trigger"; + #trigger-source-cells = <0>; + pwms = <&ad4134_odr_generator 0 1000000 0>; + }; + clocks { cnv_ext_clk: ext-clk { #clock-cells = <0x0>; @@ -88,8 +94,9 @@ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clkc 15 &spi_clk>; clock-names = "s_axi_aclk", "spi_clk"; - num-cs = <1>; - + dmas = <&rx_dma 0>; + dma-names = "offload0-rx"; + trigger-sources = <&trigger_pwm>; #address-cells = <0x1>; #size-cells = <0x0>; @@ -136,12 +143,8 @@ clocks = <&cnv_ext_clk>; clock-names = "cnv_ext_clk"; - dmas = <&rx_dma 0>; - dma-names = "rx"; - - pwms = <&ad4134_odr_generator 0 0 - &ad4134_odr_generator 1 0>; - pwm-names = "trigger_pwm","odr_pwm"; + pwm-names = "odr"; + pwms = <&ad4134_odr_generator 1 1000000 0>; avdd5-supply = <&avdd5>; avdd1v8-supply = <&avdd1v8>; From a8d69c7a1999a709d3b3fa86f5fbaf13a62a0fd8 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 10:40:22 -0300 Subject: [PATCH 62/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Adjust AXI clock generator names Adjust AXI clock generator names and output names making it follow the same configuration as in zynq-zed-adv7511-ad4134-24.dts. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index 9f971914d3ed5c..d83968768adaff 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -123,8 +123,8 @@ reg = <0x44b10000 0x10000>; #clock-cells = <0>; clocks = <&clkc 15>, <&clkc 15>; - clock-names = "s_axi_aclk", "clkin1"; - clock-output-names = "spi_clk"; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "clkin1", "spi_clk"; }; }; From 89eb3b6450e35054fa8dd1a8574b6a7046e52081 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 10:50:27 -0300 Subject: [PATCH 63/75] ARM: dts: zynq-zed-adv7511-cn0561-24: Adjust AXI clock generator names Adjust AXI clock generator names and output names making it follow the same configuration as in zynq-zed-adv7511-ad4134-24.dts. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts index a0c86b57ca0048..cbf6ae4418c6e2 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts @@ -166,8 +166,8 @@ reg = <0x44b10000 0x10000>; #clock-cells = <0>; clocks = <&clkc 15>, <&clkc 15>; - clock-names = "s_axi_aclk", "clkin1"; - clock-output-names = "spi_clk"; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "clkin1", "spi_clk"; }; }; From 374fb0f3eff7bf863096c729e45d59f4b0945de9 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 11:27:53 -0300 Subject: [PATCH 64/75] ARM: dts: zynq-zed-adv7511-cn0561-24: Fix PWM clock cells Bump PWM Generator to version 2. Fix clock phandles used by ODR PWM device node. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts index cbf6ae4418c6e2..9afca69bf69c27 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts @@ -155,10 +155,11 @@ }; ad4134_odr_generator: odr_generator@44b00000 { - compatible = "adi,axi-pwmgen"; + compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; #pwm-cells = <2>; - clocks = <&cnv_ext_clk>; + clocks = <&clkc 15>, <&cnv_ext_clk>; + clock-names = "axi", "ext"; }; spi_clk: axi_clkgen@44b10000 { From 9260f34186e4ba0341c1fbe886958fdd603bff2d Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 19 Mar 2026 11:30:02 -0300 Subject: [PATCH 65/75] ARM: dts: zynq-zed-adv7511-cn0561-24: Use offload trigger arm: dts: [SQUASH] cn0561 offload Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-cn0561-24.dts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts index 9afca69bf69c27..3e1f67b4dd3598 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-cn0561-24.dts @@ -48,6 +48,12 @@ regulator-always-on; }; + trigger_pwm: adc-pwm-trigger { + compatible = "pwm-trigger"; + #trigger-source-cells = <0>; + pwms = <&ad4134_odr_generator 0 1000000 0>; + }; + clocks { cnv_ext_clk: ext-clk { #clock-cells = <0x0>; @@ -139,8 +145,9 @@ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clkc 15 &spi_clk>; clock-names = "s_axi_aclk", "spi_clk"; - num-cs = <1>; - + dmas = <&rx_dma 0>; + dma-names = "offload0-rx"; + trigger-sources = <&trigger_pwm>; #address-cells = <0x1>; #size-cells = <0x0>; @@ -187,12 +194,8 @@ clocks = <&cnv_ext_clk>; clock-names = "cnv_ext_clk"; - dmas = <&rx_dma 0>; - dma-names = "rx"; - - pwms = <&ad4134_odr_generator 0 0 - &ad4134_odr_generator 1 0>; - pwm-names = "trigger_pwm","odr_pwm"; + pwm-names = "odr"; + pwms = <&ad4134_odr_generator 1 1000000 0>; avdd5-supply = <&avdd5>; avdd1v8-supply = <&avdd1v8>; From edcd9d5c0487ad230623d81fe900f9ae163f435c Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Mon, 26 Jan 2026 14:53:46 -0300 Subject: [PATCH 66/75] ARM: dts: Add device tree for using AD4134 on ZedBoard Add device tree for high speed sample rate data capture support with AD4134. Signed-off-by: Marcelo Schmitt --- .../dts/xilinx/zynq-zed-adv7511-ad4134.dts | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts new file mode 100644 index 00000000000000..756d746ad4f054 --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134.dts @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices AD4134 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad4134 + * https://wiki.analog.com/resources/eval/user-guides/ad4134 + * + * hdl_project: + * + * Copyright (C) 2022 Analog Devices, Inc. + */ +/dts-v1/; + +#include + +#include "zynq-zed.dtsi" +#include "zynq-zed-adv7511.dtsi" + +/ { + avdd5: regulator-avdd5 { + compatible = "regulator-fixed"; + regulator-name = "avdd5"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + avdd1v8: regulator-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "avdd1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + iovdd: regulator-iovdd { + compatible = "regulator-fixed"; + regulator-name = "iovdd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + refin: regulator-refin { + compatible = "regulator-fixed"; + regulator-name = "refin"; + regulator-min-microvolt = <4096000>; + regulator-max-microvolt = <4096000>; + regulator-always-on; + }; + + trigger_pwm: adc-pwm-trigger { + compatible = "pwm-trigger"; + #trigger-source-cells = <0>; + pwms = <&ad4134_odr_generator 0 1000000 0>; + }; + + clocks { + ext_clk: ext-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "clkin"; + }; + }; +}; + +&fpga_axi { + ad4134_odr_generator: odr_generator@44b00000 { + //compatible = "adi,axi-pwmgen"; + //reg = <0x44b00000 0x10000>; + //#pwm-cells = <2>; + //clocks = <&ext_clk>; + + compatible = "adi,axi-pwmgen-2.00.a"; + reg = <0x44b00000 0x1000>; + label = "ad4134_pwm"; + #pwm-cells = <3>; + clocks = <&clkc 15>, <&ext_clk>; + clock-names = "axi", "clkin"; + }; + + rx_dma: rx-dmac@44a30000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x44a30000 0x1000>; + #dma-cells = <1>; + interrupt-parent = <&intc>; + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15>; + }; + + spi_clk: axi_clkgen@44b10000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x44b10000 0x10000>; + #clock-cells = <0>; + clocks = <&clkc 15>, <&clkc 15>; + clock-names = "s_axi_aclk", "clkin1"; + clock-output-names = "spi_clk"; + }; + + axi_spi_engine_0: spi@44a00000 { + compatible = "adi,axi-spi-engine-1.00.a"; + reg = <0x44a00000 0x10000>; + interrupt-parent = <&intc>; + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15 &spi_clk>; + clock-names = "s_axi_aclk", "spi_clk"; + dmas = <&rx_dma 0>; + dma-names = "offload0-rx"; + trigger-sources = <&trigger_pwm>; + #address-cells = <0x1>; + #size-cells = <0x0>; + + ad4134: adc@0 { + compatible = "adi,ad4134"; + reg = <0>; + spi-max-frequency = <50000000>; + avdd5-supply = <&avdd5>; + dvdd5-supply = <&avdd5>; + iovdd-supply = <&iovdd>; + refin-supply = <&refin>; + avdd1v8-supply = <&avdd1v8>; + dvdd1v8-supply = <&avdd1v8>; + clkvdd-supply = <&avdd1v8>; + clocks = <&ext_clk>; + clock-names = "clkin"; + reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>; + //pwms = <&ad4134_odr_generator 0 0 + // &ad4134_odr_generator 1 0>; + //pwm-names = "trigger_pwm","odr_pwm"; + pwm-names = "odr"; + pwms = <&ad4134_odr_generator 1 1000000 0>; + }; + }; + +}; From 2eac3721d3844a90b533267259a9b62c0d7c29e9 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Tue, 31 Mar 2026 12:15:42 -0300 Subject: [PATCH 67/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Drop spi-cpha Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index d83968768adaff..79b0d9c44dcd3e 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -106,7 +106,6 @@ spi-max-frequency = <50000000>; - spi-cpha; }; }; From 8971b04f26ce67e5773746b0f8ce69ffb3638f7d Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Wed, 22 Apr 2026 13:42:47 -0300 Subject: [PATCH 68/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Fix external clock frequency Fix the declared frequency of the external clock provided to AD7134. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index 79b0d9c44dcd3e..a01c8919da390b 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -58,7 +58,7 @@ cnv_ext_clk: ext-clk { #clock-cells = <0x0>; compatible = "fixed-clock"; - clock-frequency = <100000000>; + clock-frequency = <48000000>; clock-output-names = "cnv_ext_clk"; }; }; From 4e6431712a6659c40fe160b4f6d12971d2a635fe Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 09:30:46 -0300 Subject: [PATCH 69/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Fix external clock frequency Fix the declared frequency of the external clock provided to AD7134. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index 999cf187b64f2c..6330f7d9346c11 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -58,7 +58,7 @@ cnv_ext_clk: ext-clk { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <100000000>; + clock-frequency = <48000000>; clock-output-names = "cnv_ext_clk"; }; }; From 19cb87c7027af86e85b77118ecec184ac1862140 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 13:54:30 -0300 Subject: [PATCH 70/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Set 4-line rx-bus-width Set read bus width to 4 lines. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index 6330f7d9346c11..daf800a6e51945 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -94,6 +94,7 @@ spi-max-frequency = <50000000>; spi-cpha; + spi-rx-bus-width = <1>, <1>, <1>, <1>; /* 4 lanes of 1 bit each */ }; }; From 112c65fb6a076a40c765e48af24dd41125658690 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Thu, 23 Apr 2026 13:56:02 -0300 Subject: [PATCH 71/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Set 8-line rx-bus-width Set read bus width to 8 lines. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index a01c8919da390b..a68b93db103f35 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -105,6 +105,7 @@ reg = <0>; spi-max-frequency = <50000000>; + spi-rx-bus-width = <1>, <1>, <1>, <1>, <1>, <1>, <1>, <1>; /* 8 lanes of 1 bit each */ }; }; From 694b645510fdc2ef53557ac78ee57a489c36a09a Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 09:53:48 -0300 Subject: [PATCH 72/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Use AXI Clock as basis for PWM Previously, the PWM Generator was deriving the output signals from the external 48 MHz clock. That in turn was leading to insuficient ODR high time due to fewer FPGA clock ticks delay being configured for PWM duty cycle. Set AXI FPGA clock as reference for the PWM Generator. Now, having 100 MHz AXI FPGA clock as base clock for the PWM Generator, the ODR waveform duty takes 13 clock ticks delay which results in 130 ns ODR high time. Thus, meeting ODR timing requirements. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index daf800a6e51945..ab6fd4ffccc9ea 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -102,8 +102,8 @@ compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; #pwm-cells = <2>; - clocks = <&clkc 15>, <&cnv_ext_clk>; - clock-names = "axi", "ext"; + clocks = <&clkc 15>; + clock-names = "axi"; }; spi_clk: spi-clock-controller@44b10000 { From 2c5d7524c4fad1abf2c04652520ce015e35f011c Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 10:00:32 -0300 Subject: [PATCH 73/75] ARM: dts: zynq-zed-adv7511-ad4134-24: Set PWM cells 3rd specifier The PWM dt-bindings now accept an optional 3rd specifier (which is typically the PWM polarity flag). Although this 3rd specifier is not supported by the AXI PWM generator, the PWM users in this device tree do provide all the 3 cell specifiers. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts index ab6fd4ffccc9ea..ae638149074085 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad4134-24.dts @@ -101,7 +101,7 @@ ad4134_odr_generator: pwm@44b00000 { compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; - #pwm-cells = <2>; + #pwm-cells = <3>; clocks = <&clkc 15>; clock-names = "axi"; }; From c492e3d31deba395ae1495a3c8e6454f4f3ce9b3 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 12:04:31 -0300 Subject: [PATCH 74/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Use AXI Clock as basis for PWM Previously, the PWM Generator was deriving the output signals from the external 48 MHz clock. That in turn was leading to insuficient ODR high time due to fewer FPGA clock ticks delay being configured for PWM duty cycle. Set AXI FPGA clock as reference for the PWM Generator. Now, having 100 MHz AXI FPGA clock as base clock for the PWM Generator, the ODR waveform duty takes 13 clock ticks delay which results in 130 ns ODR high time. Thus, meeting ODR timing requirements. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index a68b93db103f35..96359acbcd2461 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -114,8 +114,8 @@ compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; #pwm-cells = <2>; - clocks = <&clkc 15>, <&cnv_ext_clk>; - clock-names = "axi", "ext"; + clocks = <&clkc 15>; + clock-names = "axi"; }; spi_clk: axi_clkgen@44b10000 { From 8e92b8e1accb97bda8a0b5a03b6f9d1a2952b25b Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Fri, 8 May 2026 12:05:01 -0300 Subject: [PATCH 75/75] ARM: dts: zynq-zed-adv7511-ad7134-24: Set PWM cells 3rd specifier The PWM dt-bindings now accept an optional 3rd specifier (which is typically the PWM polarity flag). Although this 3rd specifier is not supported by the AXI PWM generator, the PWM users in this device tree do provide all the 3 cell specifiers. Signed-off-by: Marcelo Schmitt --- arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts index 96359acbcd2461..4df7ae38ec4bc4 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7134-24.dts @@ -113,7 +113,7 @@ ad4134_odr_generator: odr_generator@44b00000 { compatible = "adi,axi-pwmgen-2.00.a"; reg = <0x44b00000 0x10000>; - #pwm-cells = <2>; + #pwm-cells = <3>; clocks = <&clkc 15>; clock-names = "axi"; };