* [PATCh v3 3/8] arm64: dts: renesas: rzv2h: Add audio clock inputs
From: John Madieu @ 2026-04-02 16:31 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Magnus Damm
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Biju Das,
john.madieu, linux-renesas-soc, linux-clk, devicetree,
linux-kernel, John Madieu
In-Reply-To: <20260402163126.12135-1-john.madieu.xa@bp.renesas.com>
Model external audio clock inputs as CPG input clocks for RZ/V2H family
SoCs (RZ/V2H, RZ/V2N, RZ/G3E), allowing the Audio Clock Generator (ADG)
to derive internal audio clocks from these external sources.
The clock frequencies are board-specific and must be overridden in the
board DTS files.
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
Changes:
v3: No changes
v2: No changes
arch/arm64/boot/dts/renesas/r9a09g047.dtsi | 27 ++++++++++++++++++++--
arch/arm64/boot/dts/renesas/r9a09g056.dtsi | 27 ++++++++++++++++++++--
arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 27 ++++++++++++++++++++--
3 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/renesas/r9a09g047.dtsi b/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
index 95a4e30a064d..1ff48c8f98e1 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
@@ -14,6 +14,27 @@ / {
#size-cells = <2>;
interrupt-parent = <&gic>;
+ audio_clka: audio-clka {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ audio_clkb: audio-clkb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ audio_clkc: audio-clkc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
audio_extal_clk: audio-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -270,8 +291,10 @@ pinctrl: pinctrl@10410000 {
cpg: clock-controller@10420000 {
compatible = "renesas,r9a09g047-cpg";
reg = <0 0x10420000 0 0x10000>;
- clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>;
- clock-names = "audio_extal", "rtxin", "qextal";
+ clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>,
+ <&audio_clka>, <&audio_clkb>, <&audio_clkc>;
+ clock-names = "audio_extal", "rtxin", "qextal",
+ "audio_clka", "audio_clkb", "audio_clkc";
#clock-cells = <2>;
#reset-cells = <1>;
#power-domain-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/r9a09g056.dtsi b/arch/arm64/boot/dts/renesas/r9a09g056.dtsi
index 40525470194e..d2ac78006f15 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g056.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g056.dtsi
@@ -32,6 +32,27 @@ / {
#size-cells = <2>;
interrupt-parent = <&gic>;
+ audio_clka: audio-clka {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ audio_clkb: audio-clkb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ audio_clkc: audio-clkc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
audio_extal_clk: audio-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -293,8 +314,10 @@ pinctrl: pinctrl@10410000 {
cpg: clock-controller@10420000 {
compatible = "renesas,r9a09g056-cpg";
reg = <0 0x10420000 0 0x10000>;
- clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>;
- clock-names = "audio_extal", "rtxin", "qextal";
+ clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>,
+ <&audio_clka>, <&audio_clkb>, <&audio_clkc>;
+ clock-names = "audio_extal", "rtxin", "qextal",
+ "audio_clka", "audio_clkb", "audio_clkc";
#clock-cells = <2>;
#reset-cells = <1>;
#power-domain-cells = <0>;
diff --git a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
index 9581af58024e..e15b47dc93d4 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
@@ -14,6 +14,27 @@ / {
#size-cells = <2>;
interrupt-parent = <&gic>;
+ audio_clka: audio-clka {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ audio_clkb: audio-clkb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ audio_clkc: audio-clkc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
audio_extal_clk: audio-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -275,8 +296,10 @@ pinctrl: pinctrl@10410000 {
cpg: clock-controller@10420000 {
compatible = "renesas,r9a09g057-cpg";
reg = <0 0x10420000 0 0x10000>;
- clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>;
- clock-names = "audio_extal", "rtxin", "qextal";
+ clocks = <&audio_extal_clk>, <&rtxin_clk>, <&qextal_clk>,
+ <&audio_clka>, <&audio_clkb>, <&audio_clkc>;
+ clock-names = "audio_extal", "rtxin", "qextal",
+ "audio_clka", "audio_clkb", "audio_clkc";
#clock-cells = <2>;
#reset-cells = <1>;
#power-domain-cells = <0>;
--
2.25.1
^ permalink raw reply related
* [PATCh v3 4/8] arm64: dts: renesas: r9a09g047: Add RZ/G3E Sound support
From: John Madieu @ 2026-04-02 16:31 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Magnus Damm
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Biju Das,
john.madieu, linux-renesas-soc, linux-clk, devicetree,
linux-kernel, John Madieu
In-Reply-To: <20260402163126.12135-1-john.madieu.xa@bp.renesas.com>
Add the rzg3e_sound node for the RZ/G3E SoC with all sub-components:
- SSI (Serial Sound Interface) units 0-9
- SSIU (Serial Sound Interface Unit) units 0-27
- SRC (Sample Rate Converter) units 0-9
- CTU (Channel Transfer Unit) units 0-7
- DVC (Digital Volume Control) units 0-1
- MIX (Mixer) units 0-1
Wire up all 5 DMA controllers (dmac0-dmac4) for each audio sub-node
with repeated channel names, so that the DMA core can pick the first
available controller.
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
Changes:
v3: Typo fix in commit description
v2:
- Remove 2-cells specifier on audio DMA assignment
- Do not update DMAC #dma-cells anymore
arch/arm64/boot/dts/renesas/r9a09g047.dtsi | 502 +++++++++++++++++++++
1 file changed, 502 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r9a09g047.dtsi b/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
index 1ff48c8f98e1..b1e567d71c26 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
@@ -918,6 +918,508 @@ rsci9: serial@12803000 {
status = "disabled";
};
+ snd_rzg3e: sound@13c00000 {
+ /*
+ * #sound-dai-cells is required
+ *
+ * Single DAI : #sound-dai-cells = <0>; <&snd_rzg3e>;
+ * Multi DAI : #sound-dai-cells = <1>; <&snd_rzg3e N>;
+ */
+ /*
+ * #clock-cells is required for audio_clkout0/1/2/3
+ *
+ * clkout : #clock-cells = <0>; <&snd_rzg3e>;
+ * clkout0/1/2/3: #clock-cells = <1>; <&snd_rzg3e N>;
+ */
+ compatible = "renesas,r9a09g047-sound";
+ reg = <0 0x13c00000 0 0x10000>, /* SCU */
+ <0 0x13c20000 0 0x10000>, /* ADG */
+ <0 0x13c30000 0 0x1000>, /* SSIU */
+ <0 0x13c31000 0 0x1F000>, /* SSI */
+ <0 0x13c50000 0 0x10000>; /* Audio DMAC peri peri */
+ reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+ clocks = <&cpg CPG_MOD 245>,
+ <&cpg CPG_MOD 394>,
+ <&cpg CPG_MOD 393>,
+ <&cpg CPG_MOD 392>,
+ <&cpg CPG_MOD 391>,
+ <&cpg CPG_MOD 390>,
+ <&cpg CPG_MOD 389>,
+ <&cpg CPG_MOD 388>,
+ <&cpg CPG_MOD 387>,
+ <&cpg CPG_MOD 386>,
+ <&cpg CPG_MOD 385>,
+ <&cpg CPG_MOD 381>,
+ <&cpg CPG_MOD 380>,
+ <&cpg CPG_MOD 379>,
+ <&cpg CPG_MOD 378>,
+ <&cpg CPG_MOD 377>,
+ <&cpg CPG_MOD 376>,
+ <&cpg CPG_MOD 375>,
+ <&cpg CPG_MOD 374>,
+ <&cpg CPG_MOD 373>,
+ <&cpg CPG_MOD 372>,
+ <&cpg CPG_MOD 371>,
+ <&cpg CPG_MOD 370>,
+ <&cpg CPG_MOD 371>,
+ <&cpg CPG_MOD 370>,
+ <&cpg CPG_MOD 368>,
+ <&cpg CPG_MOD 369>,
+ <&cpg CPG_MOD 251>,
+ <&cpg CPG_MOD 252>,
+ <&cpg CPG_MOD 253>,
+ <&cpg CPG_MOD 250>,
+ <&cpg CPG_MOD 384>,
+ <&cpg CPG_MOD 246>,
+ <&cpg CPG_MOD 247>,
+ <&cpg CPG_MOD 382>,
+ <&cpg CPG_MOD 361>,
+ <&cpg CPG_MOD 360>,
+ <&cpg CPG_MOD 359>,
+ <&cpg CPG_MOD 358>,
+ <&cpg CPG_MOD 357>,
+ <&cpg CPG_MOD 356>,
+ <&cpg CPG_MOD 355>,
+ <&cpg CPG_MOD 354>,
+ <&cpg CPG_MOD 353>,
+ <&cpg CPG_MOD 352>,
+ <&cpg CPG_MOD 248>,
+ <&cpg CPG_MOD 249>;
+ clock-names = "ssi-all",
+ "ssi.9", "ssi.8",
+ "ssi.7", "ssi.6",
+ "ssi.5", "ssi.4",
+ "ssi.3", "ssi.2",
+ "ssi.1", "ssi.0",
+ "src.9", "src.8",
+ "src.7", "src.6",
+ "src.5", "src.4",
+ "src.3", "src.2",
+ "src.1", "src.0",
+ "mix.1", "mix.0",
+ "ctu.1", "ctu.0",
+ "dvc.0", "dvc.1",
+ "clk_a", "clk_b",
+ "clk_c", "clk_i",
+ "ssif_supply",
+ "scu", "scu_x2",
+ "scu_supply",
+ "adg.ssi.9", "adg.ssi.8",
+ "adg.ssi.7", "adg.ssi.6",
+ "adg.ssi.5", "adg.ssi.4",
+ "adg.ssi.3", "adg.ssi.2",
+ "adg.ssi.1", "adg.ssi.0",
+ "audmapp", "adg";
+ power-domains = <&cpg>;
+ resets = <&cpg 225>,
+ <&cpg 235>,
+ <&cpg 234>,
+ <&cpg 233>,
+ <&cpg 232>,
+ <&cpg 231>,
+ <&cpg 230>,
+ <&cpg 229>,
+ <&cpg 228>,
+ <&cpg 227>,
+ <&cpg 226>,
+ <&cpg 236>,
+ <&cpg 238>,
+ <&cpg 237>;
+ reset-names = "ssi-all",
+ "ssi.9", "ssi.8",
+ "ssi.7", "ssi.6",
+ "ssi.5", "ssi.4",
+ "ssi.3", "ssi.2",
+ "ssi.1", "ssi.0",
+ "scu", "adg",
+ "audmapp";
+ status = "disabled";
+
+ rcar_sound,ctu {
+ ctu00: ctu-0 { };
+ ctu01: ctu-1 { };
+ ctu02: ctu-2 { };
+ ctu03: ctu-3 { };
+ ctu10: ctu-4 { };
+ ctu11: ctu-5 { };
+ ctu12: ctu-6 { };
+ ctu13: ctu-7 { };
+ };
+
+ rcar_sound,dvc {
+ dvc0: dvc-0 {
+ dmas = <&dmac0 0x1db3>, <&dmac1 0x1db3>,
+ <&dmac2 0x1db3>, <&dmac3 0x1db3>,
+ <&dmac4 0x1db3>;
+ dma-names = "tx", "tx", "tx", "tx", "tx";
+ };
+ dvc1: dvc-1 {
+ dmas = <&dmac0 0x1db4>, <&dmac1 0x1db4>,
+ <&dmac2 0x1db4>, <&dmac3 0x1db4>,
+ <&dmac4 0x1db4>;
+ dma-names = "tx", "tx", "tx", "tx", "tx";
+ };
+ };
+
+ rcar_sound,mix {
+ mix0: mix-0 { };
+ mix1: mix-1 { };
+ };
+
+ rcar_sound,src {
+ src0: src-0 {
+ interrupts = <GIC_SPI 902 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1d9f>, <&dmac0 0x1da9>,
+ <&dmac1 0x1d9f>, <&dmac1 0x1da9>,
+ <&dmac2 0x1d9f>, <&dmac2 0x1da9>,
+ <&dmac3 0x1d9f>, <&dmac3 0x1da9>,
+ <&dmac4 0x1d9f>, <&dmac4 0x1da9>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src1: src-1 {
+ interrupts = <GIC_SPI 903 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da0>, <&dmac0 0x1daa>,
+ <&dmac1 0x1da0>, <&dmac1 0x1daa>,
+ <&dmac2 0x1da0>, <&dmac2 0x1daa>,
+ <&dmac3 0x1da0>, <&dmac3 0x1daa>,
+ <&dmac4 0x1da0>, <&dmac4 0x1daa>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src2: src-2 {
+ interrupts = <GIC_SPI 904 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da1>, <&dmac0 0x1dab>,
+ <&dmac1 0x1da1>, <&dmac1 0x1dab>,
+ <&dmac2 0x1da1>, <&dmac2 0x1dab>,
+ <&dmac3 0x1da1>, <&dmac3 0x1dab>,
+ <&dmac4 0x1da1>, <&dmac4 0x1dab>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src3: src-3 {
+ interrupts = <GIC_SPI 905 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da2>, <&dmac0 0x1dac>,
+ <&dmac1 0x1da2>, <&dmac1 0x1dac>,
+ <&dmac2 0x1da2>, <&dmac2 0x1dac>,
+ <&dmac3 0x1da2>, <&dmac3 0x1dac>,
+ <&dmac4 0x1da2>, <&dmac4 0x1dac>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src4: src-4 {
+ interrupts = <GIC_SPI 906 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da3>, <&dmac0 0x1dad>,
+ <&dmac1 0x1da3>, <&dmac1 0x1dad>,
+ <&dmac2 0x1da3>, <&dmac2 0x1dad>,
+ <&dmac3 0x1da3>, <&dmac3 0x1dad>,
+ <&dmac4 0x1da3>, <&dmac4 0x1dad>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src5: src-5 {
+ interrupts = <GIC_SPI 907 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da4>, <&dmac0 0x1dae>,
+ <&dmac1 0x1da4>, <&dmac1 0x1dae>,
+ <&dmac2 0x1da4>, <&dmac2 0x1dae>,
+ <&dmac3 0x1da4>, <&dmac3 0x1dae>,
+ <&dmac4 0x1da4>, <&dmac4 0x1dae>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src6: src-6 {
+ interrupts = <GIC_SPI 908 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da5>, <&dmac0 0x1daf>,
+ <&dmac1 0x1da5>, <&dmac1 0x1daf>,
+ <&dmac2 0x1da5>, <&dmac2 0x1daf>,
+ <&dmac3 0x1da5>, <&dmac3 0x1daf>,
+ <&dmac4 0x1da5>, <&dmac4 0x1daf>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src7: src-7 {
+ interrupts = <GIC_SPI 909 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da6>, <&dmac0 0x1db0>,
+ <&dmac1 0x1da6>, <&dmac1 0x1db0>,
+ <&dmac2 0x1da6>, <&dmac2 0x1db0>,
+ <&dmac3 0x1da6>, <&dmac3 0x1db0>,
+ <&dmac4 0x1da6>, <&dmac4 0x1db0>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src8: src-8 {
+ interrupts = <GIC_SPI 910 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da7>, <&dmac0 0x1db1>,
+ <&dmac1 0x1da7>, <&dmac1 0x1db1>,
+ <&dmac2 0x1da7>, <&dmac2 0x1db1>,
+ <&dmac3 0x1da7>, <&dmac3 0x1db1>,
+ <&dmac4 0x1da7>, <&dmac4 0x1db1>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ src9: src-9 {
+ interrupts = <GIC_SPI 911 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmac0 0x1da8>, <&dmac0 0x1db2>,
+ <&dmac1 0x1da8>, <&dmac1 0x1db2>,
+ <&dmac2 0x1da8>, <&dmac2 0x1db2>,
+ <&dmac3 0x1da8>, <&dmac3 0x1db2>,
+ <&dmac4 0x1da8>, <&dmac4 0x1db2>;
+ dma-names = "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx";
+ };
+ };
+
+ rcar_sound,ssi {
+ ssi0: ssi-0 {
+ interrupts = <GIC_SPI 889 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi1: ssi-1 {
+ interrupts = <GIC_SPI 890 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi2: ssi-2 {
+ interrupts = <GIC_SPI 891 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi3: ssi-3 {
+ interrupts = <GIC_SPI 892 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi4: ssi-4 {
+ interrupts = <GIC_SPI 893 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi5: ssi-5 {
+ interrupts = <GIC_SPI 894 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi6: ssi-6 {
+ interrupts = <GIC_SPI 895 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi7: ssi-7 {
+ interrupts = <GIC_SPI 896 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi8: ssi-8 {
+ interrupts = <GIC_SPI 897 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ ssi9: ssi-9 {
+ interrupts = <GIC_SPI 898 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ rcar_sound,ssiu {
+ ssiu00: ssiu-0 {
+ dmas = <&dmac0 0x1d61>, <&dmac0 0x1d62>,
+ <&dmac1 0x1d61>, <&dmac1 0x1d62>,
+ <&dmac2 0x1d61>, <&dmac2 0x1d62>,
+ <&dmac3 0x1d61>, <&dmac3 0x1d62>,
+ <&dmac4 0x1d61>, <&dmac4 0x1d62>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu01: ssiu-1 {
+ dmas = <&dmac0 0x1d63>, <&dmac0 0x1d64>,
+ <&dmac1 0x1d63>, <&dmac1 0x1d64>,
+ <&dmac2 0x1d63>, <&dmac2 0x1d64>,
+ <&dmac3 0x1d63>, <&dmac3 0x1d64>,
+ <&dmac4 0x1d63>, <&dmac4 0x1d64>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu02: ssiu-2 {
+ dmas = <&dmac0 0x1d65>, <&dmac0 0x1d66>,
+ <&dmac1 0x1d65>, <&dmac1 0x1d66>,
+ <&dmac2 0x1d65>, <&dmac2 0x1d66>,
+ <&dmac3 0x1d65>, <&dmac3 0x1d66>,
+ <&dmac4 0x1d65>, <&dmac4 0x1d66>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu03: ssiu-3 {
+ dmas = <&dmac0 0x1d67>, <&dmac0 0x1d68>,
+ <&dmac1 0x1d67>, <&dmac1 0x1d68>,
+ <&dmac2 0x1d67>, <&dmac2 0x1d68>,
+ <&dmac3 0x1d67>, <&dmac3 0x1d68>,
+ <&dmac4 0x1d67>, <&dmac4 0x1d68>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu10: ssiu-4 {
+ dmas = <&dmac0 0x1d69>, <&dmac0 0x1d6a>,
+ <&dmac1 0x1d69>, <&dmac1 0x1d6a>,
+ <&dmac2 0x1d69>, <&dmac2 0x1d6a>,
+ <&dmac3 0x1d69>, <&dmac3 0x1d6a>,
+ <&dmac4 0x1d69>, <&dmac4 0x1d6a>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu11: ssiu-5 {
+ dmas = <&dmac0 0x1d6b>, <&dmac0 0x1d6c>,
+ <&dmac1 0x1d6b>, <&dmac1 0x1d6c>,
+ <&dmac2 0x1d6b>, <&dmac2 0x1d6c>,
+ <&dmac3 0x1d6b>, <&dmac3 0x1d6c>,
+ <&dmac4 0x1d6b>, <&dmac4 0x1d6c>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu12: ssiu-6 {
+ dmas = <&dmac0 0x1d6d>, <&dmac0 0x1d6e>,
+ <&dmac1 0x1d6d>, <&dmac1 0x1d6e>,
+ <&dmac2 0x1d6d>, <&dmac2 0x1d6e>,
+ <&dmac3 0x1d6d>, <&dmac3 0x1d6e>,
+ <&dmac4 0x1d6d>, <&dmac4 0x1d6e>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu13: ssiu-7 {
+ dmas = <&dmac0 0x1d6f>, <&dmac0 0x1d70>,
+ <&dmac1 0x1d6f>, <&dmac1 0x1d70>,
+ <&dmac2 0x1d6f>, <&dmac2 0x1d70>,
+ <&dmac3 0x1d6f>, <&dmac3 0x1d70>,
+ <&dmac4 0x1d6f>, <&dmac4 0x1d70>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu20: ssiu-8 {
+ dmas = <&dmac0 0x1d71>, <&dmac0 0x1d72>,
+ <&dmac1 0x1d71>, <&dmac1 0x1d72>,
+ <&dmac2 0x1d71>, <&dmac2 0x1d72>,
+ <&dmac3 0x1d71>, <&dmac3 0x1d72>,
+ <&dmac4 0x1d71>, <&dmac4 0x1d72>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu21: ssiu-9 {
+ dmas = <&dmac0 0x1d73>, <&dmac0 0x1d74>,
+ <&dmac1 0x1d73>, <&dmac1 0x1d74>,
+ <&dmac2 0x1d73>, <&dmac2 0x1d74>,
+ <&dmac3 0x1d73>, <&dmac3 0x1d74>,
+ <&dmac4 0x1d73>, <&dmac4 0x1d74>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu22: ssiu-10 {
+ dmas = <&dmac0 0x1d75>, <&dmac0 0x1d76>,
+ <&dmac1 0x1d75>, <&dmac1 0x1d76>,
+ <&dmac2 0x1d75>, <&dmac2 0x1d76>,
+ <&dmac3 0x1d75>, <&dmac3 0x1d76>,
+ <&dmac4 0x1d75>, <&dmac4 0x1d76>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu23: ssiu-11 {
+ dmas = <&dmac0 0x1d77>, <&dmac0 0x1d78>,
+ <&dmac1 0x1d77>, <&dmac1 0x1d78>,
+ <&dmac2 0x1d77>, <&dmac2 0x1d78>,
+ <&dmac3 0x1d77>, <&dmac3 0x1d78>,
+ <&dmac4 0x1d77>, <&dmac4 0x1d78>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu30: ssiu-12 {
+ dmas = <&dmac0 0x1d79>, <&dmac0 0x1d7a>,
+ <&dmac1 0x1d79>, <&dmac1 0x1d7a>,
+ <&dmac2 0x1d79>, <&dmac2 0x1d7a>,
+ <&dmac3 0x1d79>, <&dmac3 0x1d7a>,
+ <&dmac4 0x1d79>, <&dmac4 0x1d7a>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu31: ssiu-13 {
+ dmas = <&dmac0 0x1d7b>, <&dmac0 0x1d7c>,
+ <&dmac1 0x1d7b>, <&dmac1 0x1d7c>,
+ <&dmac2 0x1d7b>, <&dmac2 0x1d7c>,
+ <&dmac3 0x1d7b>, <&dmac3 0x1d7c>,
+ <&dmac4 0x1d7b>, <&dmac4 0x1d7c>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu32: ssiu-14 {
+ dmas = <&dmac0 0x1d7d>, <&dmac0 0x1d7e>,
+ <&dmac1 0x1d7d>, <&dmac1 0x1d7e>,
+ <&dmac2 0x1d7d>, <&dmac2 0x1d7e>,
+ <&dmac3 0x1d7d>, <&dmac3 0x1d7e>,
+ <&dmac4 0x1d7d>, <&dmac4 0x1d7e>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu33: ssiu-15 {
+ dmas = <&dmac0 0x1d7f>, <&dmac0 0x1d80>,
+ <&dmac1 0x1d7f>, <&dmac1 0x1d80>,
+ <&dmac2 0x1d7f>, <&dmac2 0x1d80>,
+ <&dmac3 0x1d7f>, <&dmac3 0x1d80>,
+ <&dmac4 0x1d7f>, <&dmac4 0x1d80>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu40: ssiu-16 {
+ dmas = <&dmac0 0x1d81>, <&dmac0 0x1d82>,
+ <&dmac1 0x1d81>, <&dmac1 0x1d82>,
+ <&dmac2 0x1d81>, <&dmac2 0x1d82>,
+ <&dmac3 0x1d81>, <&dmac3 0x1d82>,
+ <&dmac4 0x1d81>, <&dmac4 0x1d82>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu41: ssiu-17 {
+ dmas = <&dmac0 0x1d83>, <&dmac0 0x1d84>,
+ <&dmac1 0x1d83>, <&dmac1 0x1d84>,
+ <&dmac2 0x1d83>, <&dmac2 0x1d84>,
+ <&dmac3 0x1d83>, <&dmac3 0x1d84>,
+ <&dmac4 0x1d83>, <&dmac4 0x1d84>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu42: ssiu-18 {
+ dmas = <&dmac0 0x1d85>, <&dmac0 0x1d86>,
+ <&dmac1 0x1d85>, <&dmac1 0x1d86>,
+ <&dmac2 0x1d85>, <&dmac2 0x1d86>,
+ <&dmac3 0x1d85>, <&dmac3 0x1d86>,
+ <&dmac4 0x1d85>, <&dmac4 0x1d86>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu43: ssiu-19 {
+ dmas = <&dmac0 0x1d87>, <&dmac0 0x1d88>,
+ <&dmac1 0x1d87>, <&dmac1 0x1d88>,
+ <&dmac2 0x1d87>, <&dmac2 0x1d88>,
+ <&dmac3 0x1d87>, <&dmac3 0x1d88>,
+ <&dmac4 0x1d87>, <&dmac4 0x1d88>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu50: ssiu-20 {
+ dmas = <&dmac0 0x1d89>, <&dmac0 0x1d8a>,
+ <&dmac1 0x1d89>, <&dmac1 0x1d8a>,
+ <&dmac2 0x1d89>, <&dmac2 0x1d8a>,
+ <&dmac3 0x1d89>, <&dmac3 0x1d8a>,
+ <&dmac4 0x1d89>, <&dmac4 0x1d8a>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu60: ssiu-21 {
+ dmas = <&dmac0 0x1d8b>, <&dmac0 0x1d8c>,
+ <&dmac1 0x1d8b>, <&dmac1 0x1d8c>,
+ <&dmac2 0x1d8b>, <&dmac2 0x1d8c>,
+ <&dmac3 0x1d8b>, <&dmac3 0x1d8c>,
+ <&dmac4 0x1d8b>, <&dmac4 0x1d8c>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu70: ssiu-22 {
+ dmas = <&dmac0 0x1d8d>, <&dmac0 0x1d8e>,
+ <&dmac1 0x1d8d>, <&dmac1 0x1d8e>,
+ <&dmac2 0x1d8d>, <&dmac2 0x1d8e>,
+ <&dmac3 0x1d8d>, <&dmac3 0x1d8e>,
+ <&dmac4 0x1d8d>, <&dmac4 0x1d8e>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu80: ssiu-23 {
+ dmas = <&dmac0 0x1d8f>, <&dmac0 0x1d90>,
+ <&dmac1 0x1d8f>, <&dmac1 0x1d90>,
+ <&dmac2 0x1d8f>, <&dmac2 0x1d90>,
+ <&dmac3 0x1d8f>, <&dmac3 0x1d90>,
+ <&dmac4 0x1d8f>, <&dmac4 0x1d90>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu90: ssiu-24 {
+ dmas = <&dmac0 0x1d91>, <&dmac0 0x1d92>,
+ <&dmac1 0x1d91>, <&dmac1 0x1d92>,
+ <&dmac2 0x1d91>, <&dmac2 0x1d92>,
+ <&dmac3 0x1d91>, <&dmac3 0x1d92>,
+ <&dmac4 0x1d91>, <&dmac4 0x1d92>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu91: ssiu-25 {
+ dmas = <&dmac0 0x1d93>, <&dmac0 0x1d94>,
+ <&dmac1 0x1d93>, <&dmac1 0x1d94>,
+ <&dmac2 0x1d93>, <&dmac2 0x1d94>,
+ <&dmac3 0x1d93>, <&dmac3 0x1d94>,
+ <&dmac4 0x1d93>, <&dmac4 0x1d94>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu92: ssiu-26 {
+ dmas = <&dmac0 0x1d95>, <&dmac0 0x1d96>,
+ <&dmac1 0x1d95>, <&dmac1 0x1d96>,
+ <&dmac2 0x1d95>, <&dmac2 0x1d96>,
+ <&dmac3 0x1d95>, <&dmac3 0x1d96>,
+ <&dmac4 0x1d95>, <&dmac4 0x1d96>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ ssiu93: ssiu-27 {
+ dmas = <&dmac0 0x1d97>, <&dmac0 0x1d98>,
+ <&dmac1 0x1d97>, <&dmac1 0x1d98>,
+ <&dmac2 0x1d97>, <&dmac2 0x1d98>,
+ <&dmac3 0x1d97>, <&dmac3 0x1d98>,
+ <&dmac4 0x1d97>, <&dmac4 0x1d98>;
+ dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
+ };
+ };
+ };
+
wdt1: watchdog@14400000 {
compatible = "renesas,r9a09g047-wdt", "renesas,r9a09g057-wdt";
reg = <0 0x14400000 0 0x400>;
--
2.25.1
^ permalink raw reply related
* [PATCh v3 5/8] arm64: dts: renesas: rzg3e-smarc-som: Add Versa3 clock generator
From: John Madieu @ 2026-04-02 16:31 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Magnus Damm
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Biju Das,
john.madieu, linux-renesas-soc, linux-clk, devicetree,
linux-kernel, John Madieu
In-Reply-To: <20260402163126.12135-1-john.madieu.xa@bp.renesas.com>
Add the Renesas 5P35023 (Versa3) programmable clock generator on the
I2C2 bus along with its 24MHz input clock (x2 oscillator) to feed the
audio subsystem.
The Versa3 provides the following audio-related clock outputs:
- Output 0: 24MHz (reference)
- Output 1: 12.288MHz (audio, 48kHz family)
- Output 2: 11.2896MHz (audio, 44.1kHz family)
- Output 3: 12.288MHz (audio)
These clocks are required for the audio codec found on the RZ/G3E SMARC
EVK.
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
Changes:
v3: No changes
v2: No changes
.../boot/dts/renesas/rzg3e-smarc-som.dtsi | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
index d978619155d2..89428c804efb 100644
--- a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
@@ -77,6 +77,12 @@ reg_vdd0p8v_others: regulator-vdd0p8v-others {
regulator-always-on;
};
+ x2: x2-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
+
/* 32.768kHz crystal */
x3: x3-clock {
compatible = "fixed-clock";
@@ -130,6 +136,20 @@ raa215300: pmic@12 {
interrupts-extended = <&pinctrl RZG3E_GPIO(S, 1) IRQ_TYPE_EDGE_FALLING>;
};
+
+ versa3: clock-generator@68 {
+ compatible = "renesas,5p35023";
+ reg = <0x68>;
+ #clock-cells = <1>;
+ clocks = <&x2>;
+
+ assigned-clocks = <&versa3 0>, <&versa3 1>,
+ <&versa3 2>, <&versa3 3>,
+ <&versa3 4>, <&versa3 5>;
+ assigned-clock-rates = <24000000>, <12288000>,
+ <11289600>, <12288000>,
+ <25000000>, <25000000>;
+ };
};
&i3c {
--
2.25.1
^ permalink raw reply related
* [PATCh v3 6/8] arm64: dts: renesas: rzg3e-smarc-som: Add I2C1 support
From: John Madieu @ 2026-04-02 16:31 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Magnus Damm
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Biju Das,
john.madieu, linux-renesas-soc, linux-clk, devicetree,
linux-kernel, John Madieu
In-Reply-To: <20260402163126.12135-1-john.madieu.xa@bp.renesas.com>
Add and enable I2C1 controller support with pin configuration.
The I2C1 bus is routed to the carrier board and used for peripherals
such as the audio codec.
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
Changes:
v3: No changes
v2: No changes
arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
index 89428c804efb..493f6783d583 100644
--- a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
@@ -32,6 +32,7 @@ / {
aliases {
ethernet0 = ð0;
ethernet1 = ð1;
+ i2c1 = &i2c1;
i2c2 = &i2c2;
mmc0 = &sdhi0;
mmc2 = &sdhi2;
@@ -118,6 +119,12 @@ &gpu {
mali-supply = <®_vdd0p8v_others>;
};
+&i2c1 {
+ pinctrl-0 = <&i2c1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&i2c2 {
pinctrl-0 = <&i2c2_pins>;
pinctrl-names = "default";
@@ -255,6 +262,11 @@ ctrl {
};
};
+ i2c1_pins: i2c1 {
+ pinmux = <RZG3E_PORT_PINMUX(3, 2, 1)>, /* SCL1 */
+ <RZG3E_PORT_PINMUX(3, 3, 1)>; /* SDA1 */
+ };
+
i2c2_pins: i2c {
pinmux = <RZG3E_PORT_PINMUX(3, 4, 1)>, /* SCL2 */
<RZG3E_PORT_PINMUX(3, 5, 1)>; /* SDA2 */
--
2.25.1
^ permalink raw reply related
* [PATCh v3 7/8] arm64: dts: renesas: rzg3e-smarc-som: add audio pinmux definitions
From: John Madieu @ 2026-04-02 16:31 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Magnus Damm
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Biju Das,
john.madieu, linux-renesas-soc, linux-clk, devicetree,
linux-kernel, John Madieu
In-Reply-To: <20260402163126.12135-1-john.madieu.xa@bp.renesas.com>
Add pinmux definitions for SSI3/SSI4 audio interface on RZ/G3E SMARC SoM:
- sound_clk_pins: AUDIO_CLKB and AUDIO_CLKC clock outputs
- sound_pins: SSI3_SCK, SSI3_WS, SSI3_SDATA (playback) and
SSI4_SDATA (capture)
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
Changes:
v3: No changes
v2: No changes
arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
index 493f6783d583..f4532a06cc31 100644
--- a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
@@ -353,6 +353,18 @@ sd2-pwen {
};
};
+ sound_clk_pins: sound_clk {
+ pinmux = <RZG3E_PORT_PINMUX(4, 2, 8)>, /* AUDIO_CLKB */
+ <RZG3E_PORT_PINMUX(4, 3, 8)>; /* AUDIO_CLKC */
+ };
+
+ sound_pins: sound {
+ pinmux = <RZG3E_PORT_PINMUX(0, 3, 9)>, /* SSI3_SCK */
+ <RZG3E_PORT_PINMUX(0, 4, 9)>, /* SSI3_WS */
+ <RZG3E_PORT_PINMUX(0, 2, 9)>, /* SSI3_SDATA */
+ <RZG3E_PORT_PINMUX(0, 5, 9)>; /* SSI4_SDATA */
+ };
+
xspi_pins: xspi0 {
pinmux = <RZG3E_PORT_PINMUX(M, 0, 0)>, /* XSPI0_IO0 */
<RZG3E_PORT_PINMUX(M, 1, 0)>, /* XSPI0_IO1 */
--
2.25.1
^ permalink raw reply related
* [PATCh v3 8/8] arm64: dts: renesas: r9a09g047e57-smarc: add DA7212 audio codec support
From: John Madieu @ 2026-04-02 16:31 UTC (permalink / raw)
To: Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Magnus Damm
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Biju Das,
john.madieu, linux-renesas-soc, linux-clk, devicetree,
linux-kernel, John Madieu
In-Reply-To: <20260402163126.12135-1-john.madieu.xa@bp.renesas.com>
RZ/G3E SMARC board has a DA7212 audio codec connected via I2C1 for
sound input/output using SSI3/SSI4 where:
- The codec receives its master clock from the Versa3 clock
generator present on the SoM
- SSI4 shares clock pins with SSI3 to provide a separate data
line for full-duplex audio capture.
Enable audio support on RZ/G3E SMARC2 EVK boards with a DA7212 audio codec.
Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
---
Changes:
v3: No changes
v2: No changes
.../boot/dts/renesas/r9a09g047e57-smarc.dts | 114 ++++++++++++++++++
1 file changed, 114 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r9a09g047e57-smarc.dts b/arch/arm64/boot/dts/renesas/r9a09g047e57-smarc.dts
index 6372f582a7c4..7defd342294a 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g047e57-smarc.dts
+++ b/arch/arm64/boot/dts/renesas/r9a09g047e57-smarc.dts
@@ -32,6 +32,37 @@
#include "rzg3e-smarc-som.dtsi"
#include "renesas-smarc2.dtsi"
+/*
+ * SSI-DA7212
+ *
+ * These commands are required when Playback/Capture
+ *
+ * amixer -q cset name='Aux Switch' on
+ * amixer -q cset name='Mixin Left Aux Left Switch' on
+ * amixer -q cset name='Mixin Right Aux Right Switch' on
+ * amixer -q cset name='ADC Switch' on
+ * amixer -q cset name='Mixout Right Mixin Right Switch' off
+ * amixer -q cset name='Mixout Left Mixin Left Switch' off
+ * amixer -q cset name='Headphone Volume' 70%
+ * amixer -q cset name='Headphone Switch' on
+ * amixer -q cset name='Mixout Left DAC Left Switch' on
+ * amixer -q cset name='Mixout Right DAC Right Switch' on
+ * amixer -q cset name='DAC Left Source MUX' 'DAI Input Left'
+ * amixer -q cset name='DAC Right Source MUX' 'DAI Input Right'
+ * amixer -q sset 'Mic 1 Amp Source MUX' 'MIC_P'
+ * amixer -q sset 'Mic 2 Amp Source MUX' 'MIC_P'
+ * amixer -q sset 'Mixin Left Mic 1' on
+ * amixer -q sset 'Mixin Right Mic 2' on
+ * amixer -q sset 'Mic 1' 90% on
+ * amixer -q sset 'Mic 2' 90% on
+ * amixer -q sset 'Lineout' 80% on
+ * amixer -q set "Headphone" 100% on
+ *
+ * When Capture chained with DVC, use this command to amplify sound
+ * amixer set 'DVC In',0 80%
+ * For playback, use: amixer set 'DVC Out',0 80%
+ */
+
/ {
model = "Renesas SMARC EVK version 2 based on r9a09g047e57";
compatible = "renesas,smarc2-evk", "renesas,rzg3e-smarcm",
@@ -55,6 +86,22 @@ vqmmc_sd1_pvdd: regulator-vqmmc-sd1-pvdd {
gpios-states = <0>;
states = <3300000 0>, <1800000 1>;
};
+
+ sound_card: sound {
+ compatible = "audio-graph-card";
+
+ label = "snd-rzg3e";
+
+ dais = <&rsnd_port0>; /* DA7212 */
+ };
+};
+
+&audio_clkb {
+ clock-frequency = <11289600>;
+};
+
+&audio_clkc {
+ clock-frequency = <12288000>;
};
&canfd {
@@ -99,6 +146,37 @@ &i2c0 {
pinctrl-names = "default";
};
+&i2c1 {
+ da7212: codec@1a {
+ compatible = "dlg,da7212";
+ #sound-dai-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1a>;
+
+ clocks = <&versa3 1>;
+ clock-names = "mclk";
+
+ dlg,micbias1-lvl = <2500>;
+ dlg,micbias2-lvl = <2500>;
+ dlg,dmic-data-sel = "lrise_rfall";
+ dlg,dmic-samplephase = "between_clkedge";
+ dlg,dmic-clkrate = <3000000>;
+
+ VDDA-supply = <®_1p8v>;
+ VDDSP-supply = <®_3p3v>;
+ VDDMIC-supply = <®_3p3v>;
+ VDDIO-supply = <®_1p8v>;
+
+ port {
+ da7212_endpoint: endpoint {
+ remote-endpoint = <&rsnd_endpoint0>;
+ mclk-fs = <256>;
+ };
+ };
+ };
+};
+
&keys {
pinctrl-0 = <&nmi_pins>;
pinctrl-names = "default";
@@ -280,6 +358,42 @@ &sdhi1 {
vqmmc-supply = <&vqmmc_sd1_pvdd>;
};
+&snd_rzg3e {
+ pinctrl-0 = <&sound_clk_pins &sound_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ /* audio_clkout */
+ #clock-cells = <0>;
+ clock-frequency = <11289600>;
+
+ /* Multi DAI */
+ #sound-dai-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rsnd_port0: port@0 {
+ reg = <0>;
+ rsnd_endpoint0: endpoint {
+ remote-endpoint = <&da7212_endpoint>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint0>;
+ frame-master = <&rsnd_endpoint0>;
+
+ playback = <&ssi3>, <&src1>, <&dvc1>;
+ capture = <&ssi4>, <&src0>, <&dvc0>;
+ };
+ };
+ };
+};
+
+&ssi4 {
+ shared-pin;
+};
+
&usb3_phy {
status = "okay";
};
--
2.25.1
^ permalink raw reply related
* Re: [PATCH 6/6] arm64: dts: qcom: milos: Add Adreno 810 GPU and GMU nodes
From: Alexander Koskovich @ 2026-04-02 16:36 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Akhil P Oommen,
Bjorn Andersson, Luca Weiss, linux-arm-msm, dri-devel, freedreno,
devicetree, linux-kernel
In-Reply-To: <182d58c1-21fb-4cab-8ce7-26f07d63d246@kernel.org>
On Thursday, April 2nd, 2026 at 4:22 AM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> On 02/04/2026 10:19, Krzysztof Kozlowski wrote:
> > On Wed, Apr 01, 2026 at 02:17:44AM +0000, Alexander Koskovich wrote:
> >> Add GPU and GMU devicetree nodes for the Adreno 810 GPU found on
> >> Qualcomm SM7635 (Milos) based devices.
> >>
> >> Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
> >> ---
> >> arch/arm64/boot/dts/qcom/milos.dtsi | 148 ++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 148 insertions(+)
> >>
> >> diff --git a/arch/arm64/boot/dts/qcom/milos.dtsi b/arch/arm64/boot/dts/qcom/milos.dtsi
> >> index 621f05820826..a8feb0339804 100644
> >> --- a/arch/arm64/boot/dts/qcom/milos.dtsi
> >> +++ b/arch/arm64/boot/dts/qcom/milos.dtsi
> >> @@ -7,6 +7,7 @@
> >> #include <dt-bindings/clock/qcom,milos-dispcc.h>
> >> #include <dt-bindings/clock/qcom,milos-gcc.h>
> >> #include <dt-bindings/clock/qcom,milos-gpucc.h>
> >> +#include <dt-bindings/clock/qcom,kaanapali-gxclkctl.h>
> >
> > Why? My next from 27th Match does not have Milos in that binding. Was it
> > added? It's worth mentioning in commit msg.
> >
>
> Now I checked in the cover letter - that patch was rejected. You cannot
> depend on rejected patch and still claim that this patchset is ready for
> merging. This patchset should be somehow marked that it depends on stuff
> which is wrong, usually I recommend marking it as RFC with explanation
> in cover letter WHY this is RFC (because it cannot be merged).
I don't see where the gxclkctl milos patch was rejected, there were some minor
comments that need to be addressed in a v2 though, is that what you mean by it
being rejected?
Will just mark v2 of this series as RFC.
>
> Best regards,
> Krzysztof
>
Thanks,
Alex
^ permalink raw reply
* Re: [PATCH v2 1/4] dt-bindings: usb: dwc3-xilinx: Add MMI USB support on Versal Gen2 platform
From: Krzysztof Kozlowski @ 2026-04-02 16:36 UTC (permalink / raw)
To: Pandey, Radhey Shyam, Radhey Shyam Pandey
Cc: gregkh, robh, krzk+dt, conor+dt, michal.simek, Thinh.Nguyen,
p.zabel, linux-usb, devicetree, linux-arm-kernel, linux-kernel,
git
In-Reply-To: <3d64cd29-d981-4e84-8106-8085250fc502@amd.com>
On 31/03/2026 11:18, Pandey, Radhey Shyam wrote:
>> On Tue, Mar 31, 2026 at 12:33:01AM +0530, Radhey Shyam Pandey wrote:
>>> Versal Gen2 platform multimedia integrated (MMI) module has a USB3.2 Gen
>>> 2x1 Dual Role Device IP. Introduce a new compatibility string to support
>>> it. The USB wrapper registers reside in the MMI UDH system-level control
>>> registers (SLCR) block, so instead of a dedicated reg property, add
>>> xlnx,usb-syscon phandle with four cells specifying register offsets for
>>> USB2 PHY, USB3 PHY, USB DRD, and USB power configuration within the SLCR.
>>>
>>> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
>>> ---
>>> Changes for v2:
>>> - Add blank line after compatible as suggested by Krzysztof.
>>> - Retain the mmi suffix in the compatible string, as this USB 3.2 Gen2
>>> IP from Synopsys is part of the dedicated Multimedia Interface. The
>>> Versal Gen2 platform also includes a separate USB 2.0 controller,
>>> and the mmi suffix uniquely distinguishes between the two USB
>>> controllers. MMI is an independent subsystem particularly targeted for
>>> deployment in Multi-Media related applications. The MMI block include
>>> following submodules: UDH: USB3.2 Gen 2x1 Dual Role Device, DisplayPort
>>> Transmit Controller, Security Module (ESM) for DisplayPort and HDMI
>>> Controllers, DP AUX-I2C PHY.
>>> - For MMI USB define parent address space i.e UDH block.
>>> - Fix inconsistent MHz spacing to use SI convention with spaces.
>>> - Move description before $ref and items in xlnx,usb-syscon property.
>>> - Restore original zynqmp-dwc3 example, add new versal2-mmi-dwc3 example.
>>> - Use 'usb' node name (without unit address) for versal2 example since
>>> it has no reg property.
>>> - Use 1/1 address/size configuration in versal2 example, use lowercase
>>> hex in syscon offsets.
>>> ---
>>> .../devicetree/bindings/usb/dwc3-xilinx.yaml | 70 ++++++++++++++++++-
>>> 1 file changed, 67 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml b/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml
>>> index d6823ef5f9a7..5e31b961aff7 100644
>>> --- a/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml
>>> +++ b/Documentation/devicetree/bindings/usb/dwc3-xilinx.yaml
>>> @@ -15,6 +15,8 @@ properties:
>>> - enum:
>>> - xlnx,zynqmp-dwc3
>>> - xlnx,versal-dwc3
>>> + - xlnx,versal2-mmi-dwc3
>> I am not going to ask the same questions.
>
> I have provided the explanation in v2 changelog.
> Retain the mmi suffix in the compatible string, as this USB 3.2 Gen2
> IP from Synopsys is part of the dedicated Multimedia Interface. The
> Versal Gen2 platform also includes a separate USB 2.0 controller,
> and the mmi suffix uniquely distinguishes between the two USB
> controllers.
>
> Let me know if you still have reservation in this approach (using
> <vendor>,<soc>-<subsystem>-<ip>). Or any other alternative
> based on IP version etc please suggest.
Commit msg must explain that you have two different devices. And then
explain what is the difference between versal2-dwc3 and versal2-mmi-dwc3.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 6/6] arm64: dts: qcom: milos: Add Adreno 810 GPU and GMU nodes
From: Krzysztof Kozlowski @ 2026-04-02 16:38 UTC (permalink / raw)
To: Alexander Koskovich
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Akhil P Oommen,
Bjorn Andersson, Luca Weiss, linux-arm-msm, dri-devel, freedreno,
devicetree, linux-kernel
In-Reply-To: <_oKtywl2hPElduEp5xQuU-pvfR8_24TNztuXf3Il3DaaddUmg04Z27u2uYnUtox8G44_zuniSoDZTSJMMW44-HNTXLFJkKCjslAeEe96u9Y=@pm.me>
On 02/04/2026 18:36, Alexander Koskovich wrote:
>>>> @@ -7,6 +7,7 @@
>>>> #include <dt-bindings/clock/qcom,milos-dispcc.h>
>>>> #include <dt-bindings/clock/qcom,milos-gcc.h>
>>>> #include <dt-bindings/clock/qcom,milos-gpucc.h>
>>>> +#include <dt-bindings/clock/qcom,kaanapali-gxclkctl.h>
>>>
>>> Why? My next from 27th Match does not have Milos in that binding. Was it
>>> added? It's worth mentioning in commit msg.
>>>
>>
>> Now I checked in the cover letter - that patch was rejected. You cannot
>> depend on rejected patch and still claim that this patchset is ready for
>> merging. This patchset should be somehow marked that it depends on stuff
>> which is wrong, usually I recommend marking it as RFC with explanation
>> in cover letter WHY this is RFC (because it cannot be merged).
>
> I don't see where the gxclkctl milos patch was rejected, there were some minor
> comments that need to be addressed in a v2 though, is that what you mean by it
> being rejected?
There is no v2, so that patch at that time could not go in, could not be
accepted, could not be used as a working dependency.
>
> Will just mark v2 of this series as RFC.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH 0/2] gpio: Add EIO GPIO support
From: Shubhrajyoti Datta @ 2026-04-02 16:38 UTC (permalink / raw)
To: linux-kernel
Cc: git, shubhrajyoti.datta, Shubhrajyoti Datta, Srinivas Neeli,
Michal Simek, Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
linux-arm-kernel
Add the EIO GPIO support.
Add the dt description and the compatible to the driver.
Shubhrajyoti Datta (2):
dt-bindings: gpio: Add eio gpio node to gpio-zynq
gpio: zynq: Add eio gpio support
.../devicetree/bindings/gpio/gpio-zynq.yaml | 14 +++++++++++++-
drivers/gpio/gpio-zynq.c | 12 ++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
--
2.34.1
^ permalink raw reply
* [PATCH 1/2] dt-bindings: gpio: Add eio gpio node to gpio-zynq
From: Shubhrajyoti Datta @ 2026-04-02 16:38 UTC (permalink / raw)
To: linux-kernel
Cc: git, shubhrajyoti.datta, Shubhrajyoti Datta, Srinivas Neeli,
Michal Simek, Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
linux-arm-kernel
In-Reply-To: <20260402163840.938417-1-shubhrajyoti.datta@amd.com>
Add the EIO gpio node to the device tree.
The EIO GPIO block exposes only bank 0 and bank 1 to
multiplexed I/O pins, providing a fixed total of 52 GPIO lines
(2 banks × 26 pins). Enforce this hardware constraint by requiring
exactly 52 entries in gpio-line-names for the EIO variant.
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
---
.../devicetree/bindings/gpio/gpio-zynq.yaml | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
index 5e2496379a3c..b8dd279753a5 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
+++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
@@ -16,6 +16,7 @@ properties:
- xlnx,zynqmp-gpio-1.0
- xlnx,versal-gpio-1.0
- xlnx,pmc-gpio-1.0
+ - xlnx,eio-gpio-1.0
reg:
maxItems: 1
@@ -30,7 +31,7 @@ properties:
gpio-line-names:
description: strings describing the names of each gpio line
- minItems: 58
+ minItems: 52
maxItems: 174
interrupt-controller: true
@@ -89,6 +90,17 @@ allOf:
minItems: 116
maxItems: 116
+ - if:
+ properties:
+ compatible:
+ enum:
+ - xlnx,eio-gpio-1.0
+ then:
+ properties:
+ gpio-line-names:
+ minItems: 52
+ maxItems: 52
+
required:
- compatible
- reg
--
2.34.1
^ permalink raw reply related
* [PATCH 2/2] gpio: zynq: Add eio gpio support
From: Shubhrajyoti Datta @ 2026-04-02 16:38 UTC (permalink / raw)
To: linux-kernel
Cc: git, shubhrajyoti.datta, Shubhrajyoti Datta, Srinivas Neeli,
Michal Simek, Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
linux-arm-kernel
In-Reply-To: <20260402163840.938417-1-shubhrajyoti.datta@amd.com>
Add support for the EIO GPIO controller found on
xa2ve3288 silicon.
The EIO GPIO block provides access to multiplexed I/O pins exposed
through the EIO interface. Only bank 0 and bank 1 are connected to
external MIO pins, with 26 GPIOs per bank (52 GPIOs total). This
change extends the Zynq GPIO driver to support the EIO GPIO
variant.
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
---
drivers/gpio/gpio-zynq.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
index 571e366624d2..8118ae3412c2 100644
--- a/drivers/gpio/gpio-zynq.c
+++ b/drivers/gpio/gpio-zynq.c
@@ -25,6 +25,7 @@
#define VERSAL_GPIO_MAX_BANK 4
#define PMC_GPIO_MAX_BANK 5
#define VERSAL_UNUSED_BANKS 2
+#define EIO_GPIO_MAX_BANK 2
#define ZYNQ_GPIO_BANK0_NGPIO 32
#define ZYNQ_GPIO_BANK1_NGPIO 22
@@ -818,6 +819,16 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, zynq_gpio_runtime_resume, NULL)
};
+static const struct zynq_platform_data eio_gpio_def = {
+ .label = "eio_gpio",
+ .ngpio = 52,
+ .max_bank = EIO_GPIO_MAX_BANK,
+ .bank_min[0] = 0,
+ .bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
+ .bank_min[1] = 26,
+ .bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */
+};
+
static const struct zynq_platform_data versal_gpio_def = {
.label = "versal_gpio",
.quirks = GPIO_QUIRK_VERSAL,
@@ -882,6 +893,7 @@ static const struct of_device_id zynq_gpio_of_match[] = {
{ .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def },
+ { .compatible = "xlnx,eio-gpio-1.0", .data = &eio_gpio_def },
{ /* end of table */ }
};
MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 1/2] dt-bindings: gpio: Add eio gpio node to gpio-zynq
From: Krzysztof Kozlowski @ 2026-04-02 16:46 UTC (permalink / raw)
To: Shubhrajyoti Datta, linux-kernel
Cc: git, shubhrajyoti.datta, Srinivas Neeli, Michal Simek,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
linux-arm-kernel
In-Reply-To: <20260402163840.938417-2-shubhrajyoti.datta@amd.com>
On 02/04/2026 18:38, Shubhrajyoti Datta wrote:
> Add the EIO gpio node to the device tree.
What is EIO? A name of new SoC? Or you forgot to include the SoC here?
> The EIO GPIO block exposes only bank 0 and bank 1 to
> multiplexed I/O pins, providing a fixed total of 52 GPIO lines
> (2 banks × 26 pins). Enforce this hardware constraint by requiring
> exactly 52 entries in gpio-line-names for the EIO variant.
Don't describe the syntax. We can read the diff.
>
> Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
> ---
>
> .../devicetree/bindings/gpio/gpio-zynq.yaml | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
> index 5e2496379a3c..b8dd279753a5 100644
> --- a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
> +++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
> @@ -16,6 +16,7 @@ properties:
> - xlnx,zynqmp-gpio-1.0
> - xlnx,versal-gpio-1.0
> - xlnx,pmc-gpio-1.0
> + - xlnx,eio-gpio-1.0
Please keep some sane ordering.
>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: gpio: Add eio gpio node to gpio-zynq
From: Krzysztof Kozlowski @ 2026-04-02 16:48 UTC (permalink / raw)
To: Shubhrajyoti Datta, linux-kernel
Cc: git, shubhrajyoti.datta, Srinivas Neeli, Michal Simek,
Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-gpio, devicetree,
linux-arm-kernel
In-Reply-To: <c28e97b2-4266-4a32-b70d-049518c606fe@kernel.org>
On 02/04/2026 18:46, Krzysztof Kozlowski wrote:
> On 02/04/2026 18:38, Shubhrajyoti Datta wrote:
>> Add the EIO gpio node to the device tree.
>
> What is EIO? A name of new SoC? Or you forgot to include the SoC here?
>
>
>> The EIO GPIO block exposes only bank 0 and bank 1 to
>> multiplexed I/O pins, providing a fixed total of 52 GPIO lines
>> (2 banks × 26 pins). Enforce this hardware constraint by requiring
>> exactly 52 entries in gpio-line-names for the EIO variant.
>
> Don't describe the syntax. We can read the diff.
>
I also receive immediate Out of office bounces when replying. Please do
not cc addresses of people who cannot set up correctly their
autoresponder and send to open source Out of office messages.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v5 0/3] riscv: dts: spacemit: Add PMIC regulators usb pcie
From: Han Gao @ 2026-04-02 16:54 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
Changes in v5:
- Add Chukun Pan as co-author
- patch 2:
Rename regulator using Chukun version
Restore vcc_5v0
Restore vin-supply in vcc4v0
- patch 3:
Restore usb3_hub_5v and use the Chukun version, now called vcc5v0_usb30
Restore vdd-supply from USB hub nodes
- Link to v4: https://lore.kernel.org/linux-riscv/cover.1774974017.git.gaohan@iscas.ac.cn/
Han Gao (3):
riscv: dts: spacemit: Enable i2c8 adapter for OrangePi RV2
riscv: dts: spacemit: Define the P1 PMIC regulators for OrangePi RV2
riscv: dts: spacemit: Enable USB3.0/PCIe on OrangePi RV2
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 193 ++++++++++++++++++
1 file changed, 193 insertions(+)
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
prerequisite-patch-id: ef6e9c7b5854d0c08066b72f9a7868db8c2140eb
prerequisite-patch-id: cfe3800f8c791ec4c63e070af9628e88e0fc31b9
prerequisite-patch-id: b76493e625ae257c8adcd67874178458420e4d47
prerequisite-patch-id: 88e01dc92c83bd88ddeb78891d3088209fed8d6b
prerequisite-patch-id: 60336d10ab8322c70596d0f046b6b5c54bb24b54
prerequisite-patch-id: 68c4d869548687dc115dd91e2ffb8f4c11482d86
prerequisite-patch-id: fdadcf964c2cb3406160edb579d99a8d5695f8e6
prerequisite-patch-id: 73b9e745338b0499b849fa4f7f9508987ab39a59
prerequisite-patch-id: cd26770c2160c3c31a406bd8a6b01ab666180ae0
prerequisite-patch-id: e5dfddc32cefae195692da8b80e19adf086e4ad7
prerequisite-patch-id: 7fd53cbe4977598f26148a4bb1cf692bbdb79a09
prerequisite-patch-id: 96ebac57bb29619b97fe95422206a685825618e9
prerequisite-patch-id: 00fac16b52f60383db3140e2885f3f7f8d14dd1a
prerequisite-patch-id: 3b7a60047b922c48e93599f621cb738856f42354
prerequisite-patch-id: 275c030b963be05dd1041451f539a130ce614277
prerequisite-patch-id: 93963424b0871e64276af0e0b2199b52e29b4603
prerequisite-patch-id: 8383188b1c01ed6280629faaa29c37d699ade241
prerequisite-patch-id: 5f8126b912b924d63d4a1e0c5eb42d212eb0d369
prerequisite-patch-id: e80af628a2e0b5f2eeb3cb1b5e7133d08bdd2c4e
prerequisite-patch-id: 0234a6dca15eb91f98a45a46604ce5b4935048a5
--
2.47.3
^ permalink raw reply
* [PATCH v5 1/3] riscv: dts: spacemit: Enable i2c8 adapter for OrangePi RV2
From: Han Gao @ 2026-04-02 16:54 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775148159.git.gaohan@iscas.ac.cn>
The adapter is used to access the SpacemiT P1 PMIC present in this board.
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 7b7331cb3c72..93880ba7bdfe 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -87,6 +87,12 @@ &pdma {
status = "okay";
};
+&i2c8 {
+ pinctrl-0 = <&i2c8_cfg>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
--
2.47.3
^ permalink raw reply related
* [PATCH v5 3/3] riscv: dts: spacemit: Enable USB3.0/PCIe on OrangePi RV2
From: Han Gao @ 2026-04-02 16:54 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775148159.git.gaohan@iscas.ac.cn>
Enable the DWC3 USB 3.0 controller and its associated usbphy2 on the
OrangePi RV2 board.
The board utilizes a Genesys Logic GL3523 USB3.0 hub.
Define a 3.3v fixed voltage regulator for PCIe and enable PCIe and
PHY-related Device Tree nodes for the OrangePi RV2.
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 80 +++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index a6de3753b876..c19952e70c31 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -23,6 +23,15 @@ chosen {
stdout-path = "serial0";
};
+ pcie_vcc_3v3: regulator-pcie-vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie_vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio K1_GPIO(116) GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
vcc_5v0: regulator-vcc-5v0 {
compatible = "regulator-fixed";
regulator-name = "vcc_5v0";
@@ -42,6 +51,16 @@ vcc4v0: regulator-vcc4v0 {
vin-supply = <&vcc_5v0>;
};
+ vcc5v0_usb30: regulator-vcc5v0-usb30 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb30";
+ enable-active-high;
+ gpios = <&gpio K1_GPIO(123) GPIO_ACTIVE_HIGH>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc_5v0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -54,6 +73,10 @@ led1 {
};
};
+&combo_phy {
+ status = "okay";
+};
+
ð0 {
phy-handle = <&rgmii0>;
phy-mode = "rgmii-id";
@@ -200,8 +223,65 @@ dldo6 {
};
};
+&pcie1_phy {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_3_cfg>;
+ status = "okay";
+};
+
+&pcie1_port {
+ phys = <&pcie1_phy>;
+ vpcie3v3-supply = <&pcie_vcc_3v3>;
+};
+
+&pcie1 {
+ vpcie3v3-supply = <&pcie_vcc_3v3>;
+ status = "okay";
+};
+
+&pcie2_phy {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_4_cfg>;
+ status = "okay";
+};
+
+&pcie2_port {
+ phys = <&pcie2_phy>;
+ vpcie3v3-supply = <&pcie_vcc_3v3>;
+};
+
+&pcie2 {
+ vpcie3v3-supply = <&pcie_vcc_3v3>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_2_cfg>;
status = "okay";
};
+
+&usbphy2 {
+ status = "okay";
+};
+
+&usb_dwc3 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb5e3,610";
+ reg = <0x1>;
+ peer-hub = <&hub_3_0>;
+ vdd-supply = <&vcc5v0_usb30>;
+ };
+
+ hub_3_0: hub@2 {
+ compatible = "usb5e3,620";
+ reg = <0x2>;
+ peer-hub = <&hub_2_0>;
+ vdd-supply = <&vcc5v0_usb30>;
+ };
+};
--
2.47.3
^ permalink raw reply related
* [PATCH v5 2/3] riscv: dts: spacemit: Define the P1 PMIC regulators for OrangePi RV2
From: Han Gao @ 2026-04-02 16:54 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Chukun Pan
Cc: devicetree, linux-riscv, spacemit, linux-kernel, Han Gao, Han Gao
In-Reply-To: <cover.1775148159.git.gaohan@iscas.ac.cn>
Define the DC power input and the 4v power as fixed regulator supplies.
Define the SpacemiT P1 PMIC voltage regulators and their constraints.
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
.../boot/dts/spacemit/k1-orangepi-rv2.dts | 107 ++++++++++++++++++
1 file changed, 107 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
index 93880ba7bdfe..a6de3753b876 100644
--- a/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-orangepi-rv2.dts
@@ -23,6 +23,25 @@ chosen {
stdout-path = "serial0";
};
+ vcc_5v0: regulator-vcc-5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_5v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vcc4v0: regulator-vcc4v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc4v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <4000000>;
+ vin-supply = <&vcc_5v0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -91,6 +110,94 @@ &i2c8 {
pinctrl-0 = <&i2c8_cfg>;
pinctrl-names = "default";
status = "okay";
+
+ pmic@41 {
+ compatible = "spacemit,p1";
+ reg = <0x41>;
+ interrupts = <64>;
+ vin1-supply = <&vcc4v0>;
+ vin2-supply = <&vcc4v0>;
+ vin3-supply = <&vcc4v0>;
+ vin4-supply = <&vcc4v0>;
+ vin5-supply = <&vcc4v0>;
+ vin6-supply = <&vcc4v0>;
+ aldoin-supply = <&vcc4v0>;
+ dldoin1-supply = <&buck5>;
+ dldoin2-supply = <&buck5>;
+
+ regulators {
+ buck1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck3_1v8: buck3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck5: buck5 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ buck6 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3450000>;
+ regulator-ramp-delay = <5000>;
+ regulator-always-on;
+ };
+
+ aldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ dldo1 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-boot-on;
+ };
+
+ dldo4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-always-on;
+ };
+
+ dldo5 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ dldo6 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-always-on;
+ };
+ };
+ };
};
&uart0 {
--
2.47.3
^ permalink raw reply related
* Re: [PATCH 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Ronald Claveau @ 2026-04-02 17:00 UTC (permalink / raw)
To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm
In-Reply-To: <5e3e8684-f893-4fb0-879e-9661820f72dd@linaro.org>
On 4/2/26 5:39 PM, Neil Armstrong wrote:
> On 4/2/26 16:27, Ronald Claveau wrote:
>> Replace the hardcoded MAX_LEVEL constant and fan register
>> with values read from platform_data (fan_reg, max_level),
>> as new MCUs need different values.
>>
>> Optionally acquire and enable a "fan" regulator supply
>> at probe time and on resume,
>> so boards that gate fan power through a regulator are handled.
>>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
>> ---
>> drivers/thermal/khadas_mcu_fan.c | 43 ++++++++++++++++++++++++++++++
>> ++++------
>> 1 file changed, 37 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/
>> khadas_mcu_fan.c
>> index d35e5313bea41..55b496625e3bd 100644
>> --- a/drivers/thermal/khadas_mcu_fan.c
>> +++ b/drivers/thermal/khadas_mcu_fan.c
>> @@ -13,13 +13,15 @@
>> #include <linux/regmap.h>
>> #include <linux/sysfs.h>
>> #include <linux/thermal.h>
>> -
>> -#define MAX_LEVEL 3
>> +#include <linux/regulator/consumer.h>
>> struct khadas_mcu_fan_ctx {
>> struct khadas_mcu *mcu;
>> + unsigned int fan_reg;
>> unsigned int level;
>> + unsigned int max_level;
>> struct thermal_cooling_device *cdev;
>> + struct regulator *power;
>> };
>> static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
>> @@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct
>> khadas_mcu_fan_ctx *ctx,
>> {
>> int ret;
>> - ret = regmap_write(ctx->mcu->regmap,
>> KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
>> - level);
>> + ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
>> if (ret)
>> return ret;
>> @@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct
>> khadas_mcu_fan_ctx *ctx,
>> static int khadas_mcu_fan_get_max_state(struct
>> thermal_cooling_device *cdev,
>> unsigned long *state)
>> {
>> - *state = MAX_LEVEL;
>> + struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
>> +
>> + *state = ctx->max_level;
>> return 0;
>> }
>> @@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct
>> thermal_cooling_device *cdev,
>> {
>> struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
>> - if (state > MAX_LEVEL)
>> + if (state > ctx->max_level)
>> return -EINVAL;
>> if (state == ctx->level)
>> @@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct
>> platform_device *pdev)
>> struct device *dev = &pdev->dev;
>> struct khadas_mcu_fan_ctx *ctx;
>> int ret;
>> + const struct khadas_mcu_fan_pdata *pdata =
>> dev_get_platdata(&pdev->dev);
>> ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
>> if (!ctx)
>> return -ENOMEM;
>> +
>> ctx->mcu = mcu;
>> + ctx->fan_reg = pdata->fan_reg;
>> + ctx->max_level = pdata->max_level;
>> +
>> + ctx->power = devm_regulator_get_optional(dev->parent, "fan");
>> + if (IS_ERR(ctx->power)) {
>> + if (PTR_ERR(ctx->power) == -ENODEV)
>> + ctx->power = NULL;
>> + else
>> + return PTR_ERR(ctx->power);
>> + }
>> +
>> + if (ctx->power) {
>> + ret = regulator_enable(ctx->power);
>> + if (ret) {
>> + dev_err(dev, "Failed to enable fan power supply: %d\n",
>> ret);
>> + return ret;
>> + }
>> + }
>> +
>> platform_set_drvdata(pdev, ctx);
>> cdev = devm_thermal_of_cooling_device_register(dev->parent,
>> @@ -130,6 +154,13 @@ static int khadas_mcu_fan_suspend(struct device
>> *dev)
>> static int khadas_mcu_fan_resume(struct device *dev)
>> {
>> struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + if (ctx->power) {
>> + ret = regulator_enable(ctx->power);
>
> Seems you're missing a regulator_disable() on suspend.
>
> Neil
>
You right, I will add the regulator_disable on suspend for next version.
Thanks for your feedback.
>> + if (ret)
>> + return ret;
>> + }
>> return khadas_mcu_fan_set_level(ctx, ctx->level);
>> }
>>
>
--
Best regards,
Ronald
^ permalink raw reply
* Re: [PATCH v2 2/4] ASoC: codecs: Add TAS675x quad-channel audio amplifier driver
From: Mark Brown @ 2026-04-02 17:10 UTC (permalink / raw)
To: Sen Wang
Cc: linux-sound, lgirdwood, robh, krzk+dt, conor+dt, devicetree,
perex, tiwai, shenghao-ding, kevin-lu, baojun.xu, niranjan.hy,
l-badrinarayanan, devarsht, v-singh1, linux-kernel
In-Reply-To: <20260401223239.1638881-3-sen@ti.com>
[-- Attachment #1: Type: text/plain, Size: 1679 bytes --]
On Wed, Apr 01, 2026 at 05:28:43PM -0500, Sen Wang wrote:
> The TAS675x (TAS6754, TAS67524) are quad-channel, digital-input
> Class-D amplifiers with an integrated DSP, controlled over I2C.
> They support I2S and TDM serial audio interfaces.
One issue that didn't get noticed last time, sorry:
> +static int tas675x_runtime_suspend(struct device *dev)
> +{
> + struct tas675x_priv *tas = dev_get_drvdata(dev);
> +
> + cancel_delayed_work_sync(&tas->fault_check_work);
> + tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
> +
> + return 0;
> +}
This cancels the work, completing any that's already running, but...
> +static void tas675x_fault_check_work(struct work_struct *work)
> +{
> + struct tas675x_priv *tas = container_of(work, struct tas675x_priv,
> + fault_check_work.work);
> +
> + if (tas675x_check_faults(tas))
> + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
> +
> + schedule_delayed_work(&tas->fault_check_work,
> + msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS));
> +}
...the work unconditionally rearms itself so we might race and requeue
(we cancel *then* wait) with the device powered off. There's the
disable_delayed_work_sync() API which should be a better fit.
> +static irqreturn_t tas675x_irq_handler(int irq, void *data)
> +{
> + struct tas675x_priv *tas = data;
> +
> + tas675x_check_faults(tas);
> +
> + /* Clear the FAULT pin latch as something latched */
> + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
> +
> + return IRQ_HANDLED;
> +}
Also, this should return IRQ_NONE if no faults were seen (to allow for
interrupt sharing and the genirq core's handling of hardware faults).
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v8 2/3] hwmon: ltc4283: Add support for the LTC4283 Swap Controller
From: Nuno Sá @ 2026-04-02 17:12 UTC (permalink / raw)
To: Guenter Roeck
Cc: Nuno Sá, linux-gpio, linux-hwmon, devicetree, linux-doc,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
Linus Walleij, Bartosz Golaszewski
In-Reply-To: <32c4c4dc-91db-4286-82e5-1d3269c76a74@roeck-us.net>
On Tue, Mar 31, 2026 at 06:31:59AM -0700, Guenter Roeck wrote:
> On 3/31/26 02:48, Nuno Sá wrote:
> > On Mon, Mar 30, 2026 at 08:47:32AM -0700, Guenter Roeck wrote:
> > > On 3/30/26 02:28, Nuno Sá wrote:
> > > > Hi Guenter, Regarding AI review, I think most of the points were
> > > > discussed in previous revisions, but there are two valid.
> > > >
> > > > On Fri, Mar 27, 2026 at 05:26:15PM +0000, Nuno Sá wrote:
> > > > > Support the LTC4283 Hot Swap Controller. The device features programmable
> > > > > current limit with foldback and independently adjustable inrush current to
> > > > > optimize the MOSFET safe operating area (SOA). The SOA timer limits MOSFET
> > > > > temperature rise for reliable protection against overstresses.
> > > > >
> > > > > An I2C interface and onboard ADC allow monitoring of board current,
> > > > > voltage, power, energy, and fault status.
> > > > >
> > > > > Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> > > > > ---
> > > > > Documentation/hwmon/index.rst | 1 +
> > > > > Documentation/hwmon/ltc4283.rst | 266 ++++++
> > > > > MAINTAINERS | 1 +
> > > > > drivers/hwmon/Kconfig | 12 +
> > > > > drivers/hwmon/Makefile | 1 +
> > > > > drivers/hwmon/ltc4283.c | 1796 +++++++++++++++++++++++++++++++++++++++
> > > > > 6 files changed, 2077 insertions(+)
> > > > >
> > > >
> > > > ...
> > > >
> > > > > +static int ltc4283_read_in_alarm(struct ltc4283_hwmon *st, u32 channel,
> > > > > + bool max_alm, long *val)
> > > > > +{
> > > > > + if (channel == LTC4283_VPWR)
> > > > > + return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_1,
> > > > > + BIT(2 + max_alm), val);
> > > > > +
> > > > > + if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_ADI_4) {
> > > > > + u32 bit = (channel - LTC4283_CHAN_ADI_1) * 2;
> > > > > + /*
> > > > > + * Lower channels go to higher bits. We also want to go +1 down
> > > > > + * in the min_alarm case.
> > > > > + */
> > > > > + return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_2,
> > > > > + BIT(7 - bit - !max_alm), val);
> > > > > + }
> > > > > +
> > > > > + if (channel >= LTC4283_CHAN_ADIO_1 && channel <= LTC4283_CHAN_ADIO_4) {
> > > > > + u32 bit = (channel - LTC4283_CHAN_ADIO_1) * 2;
> > > > > +
> > > > > + return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_3,
> > > > > + BIT(7 - bit - !max_alm), val);
> > > > > + }
> > > > > +
> > > > > + if (channel >= LTC4283_CHAN_ADIN12 && channel <= LTC4283_CHAN_ADIN34) {
> > > > > + u32 bit = (channel - LTC4283_CHAN_ADIN12) * 2;
> > > > > +
> > > > > + return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_5,
> > > > > + BIT(7 - bit - !max_alm), val);
> > > > > + }
> > > >
> > > > "Will this condition handle the ADIO12 and ADIO34 differential channels?
> > > > It looks like channels 14 and 15 fall through to the default return intended
> > > > for the DRAIN channel. Since reading the alarm implicitly clears the register
> > > > bits, could reading these ADIO alarms unintentionally clear actual DRAIN
> > > > alarms? Should the upper bound be LTC4283_CHAN_ADIO34?"
> > > >
> > > > Good catch and should be:
> > > >
> > > > - if (channel >= LTC4283_CHAN_ADIN12 && channel <= LTC4283_CHAN_ADIN34) {
> > > > + if (channel >= LTC4283_CHAN_ADIN12 && channel <= LTC4283_CHAN_ADIO34) {
> > > >
> > > > > +
> > > > > + if (channel == LTC4283_CHAN_DRNS)
> > > > > + return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_4,
> > > > > + BIT(6 + max_alm), val);
> > > > > +
> > > > > + return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_4, BIT(4 + max_alm),
> > > > > + val);
> > > > > +}
> > > >
> > > > ...
> > > >
> > > > > +
> > > > > +static int ltc4283_probe(struct i2c_client *client)
> > > > > +{
> > > > > + struct device *dev = &client->dev, *hwmon;
> > > > > + struct auxiliary_device *adev;
> > > > > + struct ltc4283_hwmon *st;
> > > > > + int ret;
> > > > > +
> > > > > + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
> > > > > + if (!st)
> > > > > + return -ENOMEM;
> > > > > +
> > > > > + if (!i2c_check_functionality(client->adapter,
> > > > > + I2C_FUNC_SMBUS_BYTE_DATA |
> > > > > + I2C_FUNC_SMBUS_WORD_DATA |
> > > > > + I2C_FUNC_SMBUS_READ_I2C_BLOCK))
> > > > > + return -EOPNOTSUPP;
> > > > > +
> > > > > + st->client = client;
> > > > > + st->map = devm_regmap_init(dev, <c4283_regmap_bus, client,
> > > > > + <c4283_regmap_config);
> > > > > + if (IS_ERR(st->map))
> > > > > + return dev_err_probe(dev, PTR_ERR(st->map),
> > > > > + "Failed to create regmap\n");
> > > > > +
> > > > > + ret = ltc4283_setup(st, dev);
> > > > > + if (ret)
> > > > > + return ret;
> > > > > +
> > > > > + hwmon = devm_hwmon_device_register_with_info(dev, "ltc4283", st,
> > > > > + <c4283_chip_info, NULL);
> > > > > +
> > > > > + if (IS_ERR(hwmon))
> > > > > + return PTR_ERR(hwmon);
> > > > > +
> > > > > + ltc4283_debugfs_init(st, client);
> > > > > +
> > > > > + if (!st->gpio_mask)
> > > > > + return 0;
> > > > > +
> > > > > + adev = devm_auxiliary_device_create(dev, "gpio", &st->gpio_mask);
> > > > > + if (!adev)
> > > > > + return dev_err_probe(dev, -ENODEV, "Failed to add GPIO device\n");
> > > >
> > > > "Does this allow multiple LTC4283 chips to probe successfully?
> > > > Without allocating a unique ID per I2C instance, it seems the first probed
> > > > chip takes the generic name. If a second chip is present, it might attempt
> > > > to register with the exact same name, resulting in a failure in device_add()
> > > > and aborting the probe."
> > > >
> > > > Also looks valid and I suspect is one of those that a quick look will
> > > > find more "offenders". I would purpose:
> > > >
> > > > - adev = devm_auxiliary_device_create(dev, "gpio", &st->gpio_mask);
> > > > + adev = __devm_auxiliary_device_create(dev, KBUILD_MODNAME, "gpio",
> > > > + &st->gpio_mask, client->addr);
> > > >
> > >
> > > That would still fail if there are multiple chips at the same I2C address
> > > on multiple I2C busses. Check drivers/gpu/drm/bridge/ti-sn65dsi86.c which has
> > > the same problem.
> >
> > I did looked at that one but totally forgot the multiple busses
> > scenario.
> >
> > >
> > > > If there's nothing else and you agree with the above, is this something
> > > > you can tweak while applying or should I spin a new version?
> > > >
> > >
> > > Please respin. Also, regarding the other concerns:
> > >
> > > Can BIT(8) * st->rsense wrap to zero on 32-bit architectures?
> > > BIT(8) is a 32-bit unsigned long and st->rsense is a u32. If a user sets a
> > > very large sense resistor value via the device tree, the multiplication could
> > > wrap to 0, causing a division-by-zero kernel panic. Should the divisor use
> > > BIT_ULL(8)?
> > >
> > > Unless I am missing something, this _can_ overflow. Try to provide a sense
> > > resistor value of 1677721600. Yes, it is unreasonable to specify such large
> > > rsense values, but why not just limit it such that it does not overflow ?
> >
> > Yes, that's pretty much my reasoning (regarding the unreasonable
> > rsense). I could just make BIT_ULL() and be done with it. I can also
> > also cap rsense to a max value but i'm not 100% what that value would
> > be. Maybe 1 ohm is already more than reasonable. I can also ask internally. Any
> > preference on this one?
> >
>
> I'd suggest to reject large (unreasonable) values. In this case, rejecting rsense
> values >= 1677721600 should solve the problem.
>
> > >
> > > Also, for the overflow concerns, if you are sure they can not happen, I'll
> > > really need to write the unit test code to make sure that this is indeed
> > > the case.
> > >
> >
> > Hmm, for the val * MILLI case, well it should not happen but given it
> > depends on user input, better if I clamp it before passing the
> > value to ltc4283_write_in_byte(). Yes, we clamp again inside the
> > write_bytes() API but not a big deal.
> >
> > For the st->power_max is again one of those cases where the values would
> > not make sense (I think - the combination of vsense_max and rsense). Just looking
> > at the code, it can overflow but this one I'm not really sure how we could handle it.
> > Maybe clamp power_max to U8_MAX and have a warning message in ltc4283_read_power_byte() if
> > we overflow long in which case we need a power64 attr?
> >
> > But even clamping does not make much sense here. The power limit register
> > is 8 bits, so if our design (rsense + vsense_max) overflows that,
> > there's nothing we can do other that erroring out.
> >
>
> Again, why not just reject unreasonable values such that calculations
> can not overflow ?
>
> In other drivers, the common approach is to reject unreeasonable values if
> provided through devicetree and to clamp them if provided through sysfs.
> I don't see why that would not work here.
Hi Guenter,
Just FYI, I intended to re-spin today but then I started to double check
the st->power_max logic. If I did not messed up 14.5uOhm is the minimum rsense
we can take so that we don't overflow long on 32bits systems. I'm not sure but
I think it's plausible to have values lower than that. So, bottom line, I
asked internally to some HW folks, who definitely know these systems
better than I do, about that 14,5 min value. I'm waiting for feedback
but it might be that we end up needing power64 attrs as you suggested
some revisions ago.
- Nuno Sá
>
> Thanks,
> Guenter
>
^ permalink raw reply
* Re: [PATCH v4 3/4] PCI: tegra: Add Tegra264 support
From: Manivannan Sadhasivam @ 2026-04-02 17:32 UTC (permalink / raw)
To: Thierry Reding
Cc: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, Karthikeyan Mitran, Hou Zhiqiang,
Thomas Petazzoni, Pali Rohár, Michal Simek, Kevin Xie,
linux-pci, devicetree, linux-tegra, linux-kernel,
linux-arm-kernel, Thierry Reding, Manikanta Maddireddy
In-Reply-To: <20260402-tegra264-pcie-v4-3-21e2e19987e8@nvidia.com>
On Thu, Apr 02, 2026 at 04:27:37PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Add a driver for the PCIe controller found on NVIDIA Tegra264 SoCs. The
> driver is very small, with its main purpose being to set up the address
> translation registers and then creating a standard PCI host using ECAM.
>
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
What is the rationale for adding a new driver? Can't you reuse the existing one?
If so, that should be mentioned in the description.
> ---
> Changes in v2:
> - specify generations applicable for PCI_TEGRA driver to avoid confusion
> - drop SPDX-FileCopyrightText tag
> - rename link_state to link_up to clarify meaning
> - replace memset() by an empty initializer
> - sanity-check only enable BAR regions
> - bring PCI link out of reset in case firmware didn't
> - use common wait times instead of defining our own
> - use core helpers to parse and print PCI link speed
> - fix multi-line comment
> - use dev_err_probe() more ubiquitously
> - fix probe sequence and error cleanup
> - use DEFINE_NOIRQ_DEV_PM_OPS() to avoid warnings for !PM_SUSPEND
> - reuse more standard registers and remove unused register definitions
> - use %pe and ERR_PTR() to print symbolic errors
> - add signed-off-by from Manikanta as the original author
> - add myself as author after significantly modifying the driver
> ---
> drivers/pci/controller/Kconfig | 10 +-
> drivers/pci/controller/Makefile | 1 +
> drivers/pci/controller/pcie-tegra264.c | 527 +++++++++++++++++++++++++++++++++
> 3 files changed, 537 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index 5aaed8ac6e44..6ead04f7bd6e 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -254,7 +254,15 @@ config PCI_TEGRA
> select IRQ_MSI_LIB
> help
> Say Y here if you want support for the PCIe host controller found
> - on NVIDIA Tegra SoCs.
> + on NVIDIA Tegra SoCs (Tegra20 through Tegra186).
> +
> +config PCIE_TEGRA264
> + bool "NVIDIA Tegra264 PCIe controller"
This driver seems to be using external MSI controller. So it can be built as a
module. Also, you have the remove() callback for some reason.
> + depends on ARCH_TEGRA || COMPILE_TEST
> + depends on PCI_MSI
Why?
> + help
> + Say Y here if you want support for the PCIe host controller found
> + on NVIDIA Tegra264 SoCs.
>
> config PCIE_RCAR_HOST
> bool "Renesas R-Car PCIe controller (host mode)"
> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
> index ac8db283f0fe..d478743b5142 100644
> --- a/drivers/pci/controller/Makefile
> +++ b/drivers/pci/controller/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o
> obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> +obj-$(CONFIG_PCIE_TEGRA264) += pcie-tegra264.o
> obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
> obj-$(CONFIG_PCIE_RCAR_EP) += pcie-rcar.o pcie-rcar-ep.o
> diff --git a/drivers/pci/controller/pcie-tegra264.c b/drivers/pci/controller/pcie-tegra264.c
> new file mode 100644
> index 000000000000..3ce1ad971bdb
> --- /dev/null
> +++ b/drivers/pci/controller/pcie-tegra264.c
> @@ -0,0 +1,527 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * PCIe host controller driver for Tegra264 SoC
> + *
> + * Copyright (c) 2022-2026, NVIDIA CORPORATION. All rights reserved.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/init.h>
> +#include <linux/interconnect.h>
> +#include <linux/interrupt.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci-ecam.h>
> +#include <linux/pci.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <soc/tegra/bpmp.h>
> +#include <soc/tegra/bpmp-abi.h>
> +#include <soc/tegra/fuse.h>
> +
> +#include "../pci.h"
> +
> +/* XAL registers */
> +#define XAL_RC_ECAM_BASE_HI 0x00
> +#define XAL_RC_ECAM_BASE_LO 0x04
> +#define XAL_RC_ECAM_BUSMASK 0x08
> +#define XAL_RC_IO_BASE_HI 0x0c
> +#define XAL_RC_IO_BASE_LO 0x10
> +#define XAL_RC_IO_LIMIT_HI 0x14
> +#define XAL_RC_IO_LIMIT_LO 0x18
> +#define XAL_RC_MEM_32BIT_BASE_HI 0x1c
> +#define XAL_RC_MEM_32BIT_BASE_LO 0x20
> +#define XAL_RC_MEM_32BIT_LIMIT_HI 0x24
> +#define XAL_RC_MEM_32BIT_LIMIT_LO 0x28
> +#define XAL_RC_MEM_64BIT_BASE_HI 0x2c
> +#define XAL_RC_MEM_64BIT_BASE_LO 0x30
> +#define XAL_RC_MEM_64BIT_LIMIT_HI 0x34
> +#define XAL_RC_MEM_64BIT_LIMIT_LO 0x38
> +#define XAL_RC_BAR_CNTL_STANDARD 0x40
> +#define XAL_RC_BAR_CNTL_STANDARD_IOBAR_EN BIT(0)
> +#define XAL_RC_BAR_CNTL_STANDARD_32B_BAR_EN BIT(1)
> +#define XAL_RC_BAR_CNTL_STANDARD_64B_BAR_EN BIT(2)
> +
> +/* XTL registers */
> +#define XTL_RC_PCIE_CFG_LINK_STATUS 0x5a
> +
> +#define XTL_RC_MGMT_PERST_CONTROL 0x218
> +#define XTL_RC_MGMT_PERST_CONTROL_PERST_O_N BIT(0)
> +
> +#define XTL_RC_MGMT_CLOCK_CONTROL 0x47c
> +#define XTL_RC_MGMT_CLOCK_CONTROL_PEX_CLKREQ_I_N_PIN_USE_CONV_TO_PRSNT BIT(9)
> +
> +struct tegra264_pcie {
> + struct device *dev;
> + bool link_up;
Keep bool types at the end to avoid holes.
> +
> + /* I/O memory */
> + void __iomem *xal;
> + void __iomem *xtl;
> + void __iomem *ecam;
> +
> + /* bridge configuration */
> + struct pci_config_window *cfg;
> + struct pci_host_bridge *bridge;
> +
> + /* wake IRQ */
> + struct gpio_desc *wake_gpio;
> + unsigned int wake_irq;
> +
> + /* BPMP and bandwidth management */
> + struct icc_path *icc_path;
> + struct tegra_bpmp *bpmp;
> + u32 ctl_id;
> +};
> +
> +static int tegra264_pcie_parse_dt(struct tegra264_pcie *pcie)
> +{
> + int err;
> +
> + pcie->wake_gpio = devm_gpiod_get_optional(pcie->dev, "nvidia,pex-wake",
You should switch to standard 'wake-gpios' property.
> + GPIOD_IN);
> + if (IS_ERR(pcie->wake_gpio))
> + return PTR_ERR(pcie->wake_gpio);
> +
> + if (pcie->wake_gpio) {
Since you are bailing out above, you don't need this check.
> + device_init_wakeup(pcie->dev, true);
> +
> + err = gpiod_to_irq(pcie->wake_gpio);
> + if (err < 0) {
> + dev_err(pcie->dev, "failed to get wake IRQ: %pe\n",
> + ERR_PTR(err));
> + return err;
> + }
> +
> + pcie->wake_irq = (unsigned int)err;
> + }
> +
> + return 0;
> +}
> +
> +static void tegra264_pcie_bpmp_set_rp_state(struct tegra264_pcie *pcie)
I don't think this function name is self explanatory. Looks like it is turning
off the PCIe controller, so how about tegra264_pcie_power_off()?
> +{
> + struct tegra_bpmp_message msg = {};
> + struct mrq_pcie_request req = {};
> + int err;
> +
> + req.cmd = CMD_PCIE_RP_CONTROLLER_OFF;
> + req.rp_ctrlr_off.rp_controller = pcie->ctl_id;
> +
> + msg.mrq = MRQ_PCIE;
> + msg.tx.data = &req;
> + msg.tx.size = sizeof(req);
> +
> + err = tegra_bpmp_transfer(pcie->bpmp, &msg);
> + if (err)
> + dev_info(pcie->dev, "failed to turn off PCIe #%u: %pe\n",
Why not dev_err()?
> + pcie->ctl_id, ERR_PTR(err));
> +
> + if (msg.rx.ret)
> + dev_info(pcie->dev, "failed to turn off PCIe #%u: %d\n",
Same here.
> + pcie->ctl_id, msg.rx.ret);
> +}
> +
> +static void tegra264_pcie_icc_set(struct tegra264_pcie *pcie)
> +{
> + u32 value, speed, width, bw;
> + int err;
> +
> + value = readw(pcie->ecam + XTL_RC_PCIE_CFG_LINK_STATUS);
> + speed = FIELD_GET(PCI_EXP_LNKSTA_CLS, value);
> + width = FIELD_GET(PCI_EXP_LNKSTA_NLW, value);
> +
> + bw = width * (PCIE_SPEED2MBS_ENC(speed) / BITS_PER_BYTE);
> + value = MBps_to_icc(bw);
So this becomes, 'width * (PCIE_SPEED2MBS_ENC(speed) / 8) * 1000 / 8'. But don't
you want, 'width * (PCIE_SPEED2MBS_ENC(speed)) * 1000 / 8'?
> +
> + err = icc_set_bw(pcie->icc_path, bw, bw);
> + if (err < 0)
> + dev_err(pcie->dev,
> + "failed to request bandwidth (%u MBps): %pe\n",
> + bw, ERR_PTR(err));
So you don't want to error out if this fails?
> +}
> +
> +/*
> + * The various memory regions used by the controller (I/O, memory, ECAM) are
> + * set up during early boot and have hardware-level protections in place. If
> + * the DT ranges don't match what's been setup, the controller won't be able
> + * to write the address endpoints properly, so make sure to validate that DT
> + * and firmware programming agree on these ranges.
> + */
> +static bool tegra264_pcie_check_ranges(struct platform_device *pdev)
> +{
> + struct tegra264_pcie *pcie = platform_get_drvdata(pdev);
> + struct device_node *np = pcie->dev->of_node;
> + struct of_pci_range_parser parser;
> + phys_addr_t phys, limit, hi, lo;
> + struct of_pci_range range;
> + struct resource *res;
> + bool status = true;
> + u32 value;
> + int err;
> +
> + err = of_pci_range_parser_init(&parser, np);
> + if (err < 0)
> + return false;
> +
> + for_each_of_pci_range(&parser, &range) {
> + unsigned int addr_hi, addr_lo, limit_hi, limit_lo, enable;
> + unsigned long type = range.flags & IORESOURCE_TYPE_BITS;
> + phys_addr_t start, end, mask;
> + const char *region = NULL;
> +
> + end = range.cpu_addr + range.size - 1;
> + start = range.cpu_addr;
> +
> + switch (type) {
> + case IORESOURCE_IO:
> + addr_hi = XAL_RC_IO_BASE_HI;
> + addr_lo = XAL_RC_IO_BASE_LO;
> + limit_hi = XAL_RC_IO_LIMIT_HI;
> + limit_lo = XAL_RC_IO_LIMIT_LO;
> + enable = XAL_RC_BAR_CNTL_STANDARD_IOBAR_EN;
> + mask = SZ_64K - 1;
> + region = "I/O";
> + break;
> +
> + case IORESOURCE_MEM:
> + if (range.flags & IORESOURCE_PREFETCH) {
> + addr_hi = XAL_RC_MEM_64BIT_BASE_HI;
> + addr_lo = XAL_RC_MEM_64BIT_BASE_LO;
> + limit_hi = XAL_RC_MEM_64BIT_LIMIT_HI;
> + limit_lo = XAL_RC_MEM_64BIT_LIMIT_LO;
> + enable = XAL_RC_BAR_CNTL_STANDARD_64B_BAR_EN;
> + region = "prefetchable memory";
> + } else {
> + addr_hi = XAL_RC_MEM_32BIT_BASE_HI;
> + addr_lo = XAL_RC_MEM_32BIT_BASE_LO;
> + limit_hi = XAL_RC_MEM_32BIT_LIMIT_HI;
> + limit_lo = XAL_RC_MEM_32BIT_LIMIT_LO;
> + enable = XAL_RC_BAR_CNTL_STANDARD_32B_BAR_EN;
> + region = "memory";
> + }
> +
> + mask = SZ_1M - 1;
> + break;
> + }
> +
> + /* not interested in anything that's not I/O or memory */
> + if (!region)
> + continue;
> +
> + /* don't check regions that haven't been enabled */
> + value = readl(pcie->xal + XAL_RC_BAR_CNTL_STANDARD);
> + if ((value & enable) == 0)
> + continue;
> +
> + hi = readl(pcie->xal + addr_hi);
> + lo = readl(pcie->xal + addr_lo);
> + phys = hi << 32 | lo;
> +
> + hi = readl(pcie->xal + limit_hi);
> + lo = readl(pcie->xal + limit_lo);
> + limit = hi << 32 | lo | mask;
> +
> + if (phys != start || limit != end) {
> + dev_err(pcie->dev,
> + "%s region mismatch: %pap-%pap -> %pap-%pap\n",
> + region, &phys, &limit, &start, &end);
> + status = false;
> + }
> + }
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam");
> + if (!res)
> + return false;
> +
> + hi = readl(pcie->xal + XAL_RC_ECAM_BASE_HI);
> + lo = readl(pcie->xal + XAL_RC_ECAM_BASE_LO);
> + phys = hi << 32 | lo;
> +
> + value = readl(pcie->xal + XAL_RC_ECAM_BUSMASK);
> + limit = phys + ((value + 1) << 20) - 1;
> +
> + if (phys != res->start || limit != res->end) {
> + dev_err(pcie->dev,
> + "ECAM region mismatch: %pap-%pap -> %pap-%pap\n",
> + &phys, &limit, &res->start, &res->end);
> + status = false;
> + }
> +
> + return status;
> +}
> +
> +static bool tegra264_pcie_link_up(struct tegra264_pcie *pcie,
> + enum pci_bus_speed *speed)
> +{
> + u16 value = readw(pcie->ecam + XTL_RC_PCIE_CFG_LINK_STATUS);
> +
> + if (value & PCI_EXP_LNKSTA_DLLLA) {
> + if (speed)
> + *speed = pcie_link_speed[FIELD_GET(PCI_EXP_LNKSTA_CLS,
> + value)];
> +
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static void tegra264_pcie_init(struct tegra264_pcie *pcie)
> +{
> + enum pci_bus_speed speed;
> + unsigned int i;
> + u32 value;
> +
> + /* bring the link out of reset */
s/link/controller or endpoint?
> + value = readl(pcie->xtl + XTL_RC_MGMT_PERST_CONTROL);
> + value |= XTL_RC_MGMT_PERST_CONTROL_PERST_O_N;
> + writel(value, pcie->xtl + XTL_RC_MGMT_PERST_CONTROL);
> +
> + if (!tegra_is_silicon()) {
This looks like some pre-silicon validation thing. Do you really want it to be
present in the upstream driver?
> + dev_info(pcie->dev,
> + "skipping link state for PCIe #%u in simulation\n",
> + pcie->ctl_id);
> + pcie->link_up = true;
> + return;
> + }
> +
> + for (i = 0; i < PCIE_LINK_WAIT_MAX_RETRIES; i++) {
> + if (tegra264_pcie_link_up(pcie, NULL))
> + break;
> +
> + usleep_range(PCIE_LINK_WAIT_US_MIN, PCIE_LINK_WAIT_US_MAX);
> + }
> +
> + if (tegra264_pcie_link_up(pcie, &speed)) {
Why are you doing it for the second time?
> + /* Per PCIe r5.0, 6.6.1 wait for 100ms after DLL up */
No need of this comment.
> + msleep(PCIE_RESET_CONFIG_WAIT_MS);
> +
> + dev_info(pcie->dev, "PCIe #%u link is up (speed: %s)\n",
> + pcie->ctl_id, pci_speed_string(speed));
> + tegra264_pcie_icc_set(pcie);
> + pcie->link_up = true;
> + } else {
> + dev_info(pcie->dev, "PCIe #%u link is down\n", pcie->ctl_id);
> +
> + value = readl(pcie->xtl + XTL_RC_MGMT_CLOCK_CONTROL);
> +
> + /*
> + * Set link state only when link fails and no hot-plug feature
> + * is present.
> + */
> + if ((value & XTL_RC_MGMT_CLOCK_CONTROL_PEX_CLKREQ_I_N_PIN_USE_CONV_TO_PRSNT) == 0) {
> + dev_info(pcie->dev,
> + "PCIe #%u link is down and not hotplug-capable, turning off\n",
> + pcie->ctl_id);
> + tegra264_pcie_bpmp_set_rp_state(pcie);
> + pcie->link_up = false;
> + } else {
> + pcie->link_up = true;
> + }
> + }
> +}
> +
> +static int tegra264_pcie_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct pci_host_bridge *bridge;
> + struct tegra264_pcie *pcie;
> + struct resource_entry *bus;
> + struct resource *res;
> + int err;
> +
> + bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct tegra264_pcie));
> + if (!bridge)
> + return dev_err_probe(dev, -ENOMEM,
> + "failed to allocate host bridge\n");
> +
> + pcie = pci_host_bridge_priv(bridge);
> + platform_set_drvdata(pdev, pcie);
> + pcie->bridge = bridge;
> + pcie->dev = dev;
> +
> + err = pinctrl_pm_select_default_state(dev);
I questioned this before:
https://lore.kernel.org/linux-pci/o5sxxdikdjwd76zsedvkpsl54nw6wrhopwsflt43y5st67mrub@uuw3yfjfqthd/
> + if (err < 0)
> + return dev_err_probe(dev, err,
> + "failed to configure sideband pins\n");
> +
> + err = tegra264_pcie_parse_dt(pcie);
> + if (err < 0)
> + return dev_err_probe(dev, err, "failed to parse device tree");
> +
> + pcie->xal = devm_platform_ioremap_resource_byname(pdev, "xal");
> + if (IS_ERR(pcie->xal))
> + return dev_err_probe(dev, PTR_ERR(pcie->xal),
> + "failed to map XAL memory\n");
> +
> + pcie->xtl = devm_platform_ioremap_resource_byname(pdev, "xtl-pri");
> + if (IS_ERR(pcie->xtl))
> + return dev_err_probe(dev, PTR_ERR(pcie->xtl),
> + "failed to map XTL-PRI memory\n");
> +
> + bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
> + if (!bus)
> + return dev_err_probe(dev, -ENODEV,
> + "failed to get bus resources\n");
> +
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam");
> + if (!res)
> + return dev_err_probe(dev, -ENXIO,
> + "failed to get ECAM resource\n");
> +
> + pcie->icc_path = devm_of_icc_get(&pdev->dev, "write");
> + if (IS_ERR(pcie->icc_path))
> + return dev_err_probe(&pdev->dev, PTR_ERR(pcie->icc_path),
> + "failed to get ICC");
> +
> + /*
> + * Parse BPMP property only for silicon, as interaction with BPMP is
> + * not needed for other platforms.
> + */
> + if (tegra_is_silicon()) {
> + pcie->bpmp = tegra_bpmp_get_with_id(dev, &pcie->ctl_id);
> + if (IS_ERR(pcie->bpmp))
> + return dev_err_probe(dev, PTR_ERR(pcie->bpmp),
> + "failed to get BPMP\n");
> + }
> +
pm_runtime_set_active()
> + pm_runtime_enable(dev);
devm_pm_runtime_enable()?
> + pm_runtime_get_sync(dev);
> +
> + /* sanity check that programmed ranges match what's in DT */
> + if (!tegra264_pcie_check_ranges(pdev)) {
> + err = -EINVAL;
> + goto put_pm;
> + }
> +
> + pcie->cfg = pci_ecam_create(dev, res, bus->res, &pci_generic_ecam_ops);
> + if (IS_ERR(pcie->cfg)) {
> + err = dev_err_probe(dev, PTR_ERR(pcie->cfg),
> + "failed to create ECAM\n");
> + goto put_pm;
> + }
> +
> + bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops;
> + bridge->sysdata = pcie->cfg;
> + pcie->ecam = pcie->cfg->win;
> +
> + tegra264_pcie_init(pcie);
> +
> + if (!pcie->link_up)
> + goto free;
goto free_ecam;
> +
> + err = pci_host_probe(bridge);
> + if (err < 0) {
> + dev_err(dev, "failed to register host: %pe\n", ERR_PTR(err));
dev_err_probe()
> + goto free;
> + }
> +
> + return err;
return 0;
> +
> +free:
> + pci_ecam_free(pcie->cfg);
> +put_pm:
> + pm_runtime_put_sync(dev);
> + pm_runtime_disable(dev);
> +
> + if (tegra_is_silicon())
> + tegra_bpmp_put(pcie->bpmp);
> +
> + return err;
> +}
> +
> +static void tegra264_pcie_remove(struct platform_device *pdev)
> +{
> + struct tegra264_pcie *pcie = platform_get_drvdata(pdev);
> +
> + /*
> + * If we undo tegra264_pcie_init() then link goes down and need
> + * controller reset to bring up the link again. Remove intention is
> + * to clean up the root bridge and re-enumerate during bind.
> + */
> + pci_lock_rescan_remove();
> + pci_stop_root_bus(pcie->bridge->bus);
> + pci_remove_root_bus(pcie->bridge->bus);
> + pci_unlock_rescan_remove();
> +
> + pm_runtime_put_sync(&pdev->dev);
> + pm_runtime_disable(&pdev->dev);
> +
> + if (tegra_is_silicon())
> + tegra_bpmp_put(pcie->bpmp);
> +
> + pci_ecam_free(pcie->cfg);
> +}
> +
> +static int tegra264_pcie_suspend_noirq(struct device *dev)
> +{
> + struct tegra264_pcie *pcie = dev_get_drvdata(dev);
> + int err;
> +
> + if (pcie->wake_gpio && device_may_wakeup(dev)) {
> + err = enable_irq_wake(pcie->wake_irq);
> + if (err < 0)
> + dev_err(dev, "failed to enable wake IRQ: %pe\n",
> + ERR_PTR(err));
> + }
> +
> + return 0;
> +}
> +
> +static int tegra264_pcie_resume_noirq(struct device *dev)
> +{
> + struct tegra264_pcie *pcie = dev_get_drvdata(dev);
> + int err;
> +
> + if (pcie->wake_gpio && device_may_wakeup(dev)) {
> + err = disable_irq_wake(pcie->wake_irq);
> + if (err < 0)
> + dev_err(dev, "failed to disable wake IRQ: %pe\n",
> + ERR_PTR(err));
> + }
> +
> + if (pcie->link_up == false)
> + return 0;
> +
> + tegra264_pcie_init(pcie);
> +
Why do you need init() here without deinit() in tegra264_pcie_suspend_noirq()?
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCh v3 03/14] ASoC: rsnd: Add reset controller support to rsnd_mod
From: Mark Brown @ 2026-04-02 17:39 UTC (permalink / raw)
To: John Madieu
Cc: Kuninori Morimoto, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
Magnus Damm, Philipp Zabel, Claudiu Beznea, Biju Das, john.madieu,
linux-sound, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20260402162436.12059-4-john.madieu.xa@bp.renesas.com>
[-- Attachment #1: Type: text/plain, Size: 339 bytes --]
On Thu, Apr 02, 2026 at 06:24:25PM +0200, John Madieu wrote:
> @@ -196,18 +197,29 @@ int rsnd_mod_init(struct rsnd_priv *priv,
> + ret = reset_control_deassert(rstc);
> + if (ret) {
> + clk_disable_unprepare(clk);
> + return ret;
> + }
I'm not seeing a call to reverse this anywhere, I'd expect one on remove
for symmetry and safety.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v11 6/6] mux: add NXP MC33978/MC34978 AMUX driver
From: Oleksij Rempel @ 2026-04-02 17:43 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lee Jones, Peter Rosin, Linus Walleij
Cc: Oleksij Rempel, kernel, linux-kernel, devicetree, linux-hwmon,
linux-gpio, David Jander
In-Reply-To: <20260402174349.3220518-1-o.rempel@pengutronix.de>
Add a mux-control driver for the 24-to-1 analog multiplexer (AMUX)
embedded in the NXP MC33978/MC34978 Multiple Switch Detection
Interface (MSDI) devices.
Assisted-by: Gemini:gemini-3.1-pro Sashiko
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
changes v11:
- no changes
changes v10:
- no changes
changes v9:
- rename mc33978-mux to mux-mc33978 in the Kconfig help
- fail if fwnode is NULL
changes v8:
- no changes
changes v7:
- Simplify the return path and local variable assignment in
mc33978_mux_set().
- Change idle_state to a signed integer to properly handle negative MUX
subsystem constants.
- Default to MUX_IDLE_AS_IS when the "idle-state" device tree property
is missing.
- Explicitly reject MUX_IDLE_DISCONNECT since the hardware does not
support disconnecting the multiplexer.
changes v6:
- parse optional idle-state property
- validate idle-state against available AMUX channels
- lower-case probe error messages
changes v5:
- no changes
changes v4:
- no changes
changes v3:
- no changes
changes v2:
- Add missing <linux/err.h> include.
- Add platform_device_id table
---
drivers/mux/Kconfig | 14 ++++
drivers/mux/Makefile | 2 +
drivers/mux/mc33978-mux.c | 141 ++++++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+)
create mode 100644 drivers/mux/mc33978-mux.c
diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig
index c68132e38138..ffe92a714096 100644
--- a/drivers/mux/Kconfig
+++ b/drivers/mux/Kconfig
@@ -45,6 +45,20 @@ config MUX_GPIO
To compile the driver as a module, choose M here: the module will
be called mux-gpio.
+config MUX_MC33978
+ tristate "NXP MC33978/MC34978 Analog Multiplexer"
+ depends on MFD_MC33978
+ help
+ MC33978/MC34978 24-to-1 analog multiplexer (AMUX) driver.
+
+ This driver provides mux-control for the analog multiplexer,
+ which can route switch voltages, temperature, and battery voltage
+ to an external ADC. Typically used with IIO ADC drivers to measure
+ analog values from the 22 switch inputs plus temperature and VBATP.
+
+ To compile the driver as a module, choose M here: the module will
+ be called mux-mc33978.
+
config MUX_MMIO
tristate "MMIO/Regmap register bitfield-controlled Multiplexer"
depends on OF
diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile
index 6e9fa47daf56..339c44b4d4f4 100644
--- a/drivers/mux/Makefile
+++ b/drivers/mux/Makefile
@@ -7,10 +7,12 @@ mux-core-objs := core.o
mux-adg792a-objs := adg792a.o
mux-adgs1408-objs := adgs1408.o
mux-gpio-objs := gpio.o
+mux-mc33978-objs := mc33978-mux.o
mux-mmio-objs := mmio.o
obj-$(CONFIG_MULTIPLEXER) += mux-core.o
obj-$(CONFIG_MUX_ADG792A) += mux-adg792a.o
obj-$(CONFIG_MUX_ADGS1408) += mux-adgs1408.o
obj-$(CONFIG_MUX_GPIO) += mux-gpio.o
+obj-$(CONFIG_MUX_MC33978) += mux-mc33978.o
obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
diff --git a/drivers/mux/mc33978-mux.c b/drivers/mux/mc33978-mux.c
new file mode 100644
index 000000000000..b44c862f0dbe
--- /dev/null
+++ b/drivers/mux/mc33978-mux.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2026 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
+/*
+ * MC33978/MC34978 Analog Multiplexer (AMUX) Driver
+ *
+ * This driver provides mux-control for the 24-to-1 analog multiplexer.
+ * The AMUX routes one of the following signals to the external AMUX pin:
+ * - Channels 0-13: SG0-SG13 switch voltages
+ * - Channels 14-21: SP0-SP7 switch voltages
+ * - Channel 22: Internal temperature diode
+ * - Channel 23: Battery voltage (VBATP)
+ *
+ * Consumer drivers (typically IIO ADC drivers) use the mux-control
+ * subsystem to select which signal to measure.
+ *
+ * Architecture:
+ * The MC33978 does not have an internal ADC. Instead, it routes analog
+ * signals to an external AMUX pin that must be connected to an external
+ * ADC (such as the SoC's internal ADC). The IIO subsystem is responsible
+ * for coordinating the mux selection and ADC sampling.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mux/driver.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/mc33978.h>
+
+/* AMUX_CTRL register field definitions */
+#define MC33978_AMUX_CTRL_MASK GENMASK(5, 0) /* 6-bit channel select */
+
+struct mc33978_mux_priv {
+ struct device *dev;
+ struct regmap *map;
+};
+
+static int mc33978_mux_set(struct mux_control *mux, int state)
+{
+ struct mux_chip *mux_chip = mux->chip;
+ struct mc33978_mux_priv *priv = mux_chip_priv(mux_chip);
+ int ret;
+
+ if (state < 0 || state >= MC33978_NUM_AMUX_CH)
+ return -EINVAL;
+
+ ret = regmap_update_bits(priv->map, MC33978_REG_AMUX_CTRL,
+ MC33978_AMUX_CTRL_MASK, state);
+ if (ret)
+ dev_err(priv->dev, "failed to set AMUX channel %d: %d\n",
+ state, ret);
+
+ return ret;
+}
+
+static const struct mux_control_ops mc33978_mux_ops = {
+ .set = mc33978_mux_set,
+};
+
+static int mc33978_mux_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mc33978_mux_priv *priv;
+ struct fwnode_handle *fwnode;
+ struct mux_chip *mux_chip;
+ struct mux_control *mux;
+ s32 idle_state;
+ int ret;
+
+ mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*priv));
+ if (IS_ERR(mux_chip))
+ return dev_err_probe(dev, PTR_ERR(mux_chip), "failed to allocate mux chip\n");
+
+ fwnode = dev_fwnode(dev->parent);
+ if (!fwnode)
+ return dev_err_probe(dev, -ENODEV, "missing parent firmware node\n");
+
+ /* Borrow the parent's firmware node so consumers can find this mux chip */
+ device_set_node(&mux_chip->dev, fwnode);
+
+ priv = mux_chip_priv(mux_chip);
+ priv->dev = dev;
+
+ priv->map = dev_get_regmap(dev->parent, NULL);
+ if (!priv->map)
+ return dev_err_probe(dev, -ENODEV, "failed to get parent regmap\n");
+
+ mux_chip->ops = &mc33978_mux_ops;
+
+ mux = &mux_chip->mux[0];
+ mux->states = MC33978_NUM_AMUX_CH;
+
+ ret = device_property_read_u32(&mux_chip->dev, "idle-state",
+ (u32 *)&idle_state);
+ if (ret < 0 && ret != -EINVAL) {
+ return dev_err_probe(dev, ret, "failed to parse idle-state\n");
+ } else if (ret == -EINVAL) {
+ mux->idle_state = MUX_IDLE_AS_IS;
+ } else {
+ if (idle_state == MUX_IDLE_DISCONNECT)
+ return dev_err_probe(dev, -EINVAL,
+ "idle-disconnect not supported by hardware\n");
+ if (idle_state != MUX_IDLE_AS_IS &&
+ (idle_state < 0 || idle_state >= MC33978_NUM_AMUX_CH))
+ return dev_err_probe(dev, -EINVAL, "invalid idle-state %d\n",
+ idle_state);
+ mux->idle_state = idle_state;
+ }
+
+ ret = devm_mux_chip_register(dev, mux_chip);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register mux chip\n");
+
+ platform_set_drvdata(pdev, mux_chip);
+
+ return 0;
+}
+
+static const struct platform_device_id mc33978_mux_id[] = {
+ { "mc33978-mux", },
+ { "mc34978-mux", },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, mc33978_mux_id);
+
+static struct platform_driver mc33978_mux_driver = {
+ .driver = {
+ .name = "mc33978-mux",
+ },
+ .probe = mc33978_mux_probe,
+ .id_table = mc33978_mux_id,
+};
+module_platform_driver(mc33978_mux_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("NXP MC33978/MC34978 Analog Multiplexer Driver");
+MODULE_LICENSE("GPL");
--
2.47.3
^ permalink raw reply related
* [PATCH v10 0/6] mfd: Add support for NXP MC33978/MC34978 MSDI
From: Oleksij Rempel @ 2026-04-02 17:43 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lee Jones, Peter Rosin, Linus Walleij
Cc: Oleksij Rempel, kernel, linux-kernel, devicetree, linux-hwmon,
linux-gpio, David Jander
changes v7:
- drop gpiolib irq fix and make pinctrl more robust against NULL point
dereference.
This series adds support for the NXP MC33978/MC34978 Multiple Switch Detection
Interface (MSDI) via the MFD framework.
Architecture overview:
* mfd: Core driver handling 2-frame pipelined SPI, regulator sequencing, and
linear irq_domain. Harvests status bits from SPI MISO MSB.
* pinctrl: Exposes 22 physical switch inputs as standard GPIOs. Proxies IRQs to
the MFD domain.
* hwmon: Exposes thermal limits, VBATP/VDDQ voltage boundaries, and dynamic
fault alarms.
* mux: Controls the 24-to-1 AMUX routing analog signals (switch voltages,
temperature, VBATP) to an external ADC.
Initial pinctrl implementation by David Jander, reworked into this MFD
architecture.
Best regards,
Oleksij
David Jander (1):
pinctrl: add NXP MC33978/MC34978 pinctrl driver
Oleksij Rempel (5):
dt-bindings: pinctrl: add NXP MC33978/MC34978 MSDI
mfd: add NXP MC33978/MC34978 core driver
pinctrl: core: Make pin group callbacks optional for pin-only drivers
hwmon: add NXP MC33978/MC34978 driver
mux: add NXP MC33978/MC34978 AMUX driver
.../bindings/pinctrl/nxp,mc33978.yaml | 158 +++
drivers/hwmon/Kconfig | 10 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/mc33978-hwmon.c | 549 +++++++++
drivers/mfd/Kconfig | 15 +
drivers/mfd/Makefile | 2 +
drivers/mfd/mc33978.c | 1088 +++++++++++++++++
drivers/mux/Kconfig | 14 +
drivers/mux/Makefile | 2 +
drivers/mux/mc33978-mux.c | 141 +++
drivers/pinctrl/Kconfig | 16 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/core.c | 41 +-
drivers/pinctrl/pinconf.c | 9 +-
drivers/pinctrl/pinctrl-mc33978.c | 1008 +++++++++++++++
include/linux/mfd/mc33978.h | 95 ++
16 files changed, 3143 insertions(+), 7 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinctrl/nxp,mc33978.yaml
create mode 100644 drivers/hwmon/mc33978-hwmon.c
create mode 100644 drivers/mfd/mc33978.c
create mode 100644 drivers/mux/mc33978-mux.c
create mode 100644 drivers/pinctrl/pinctrl-mc33978.c
create mode 100644 include/linux/mfd/mc33978.h
--
2.47.3
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox