Devicetree
 help / color / mirror / Atom feed
* [PATCH v3 1/7] arm64: dts: qcom: sm6125: Use 64 bit addressing
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	kernel test robot, Konrad Dybcio
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

SM6125's SMMU uses 36bit VAs, which is a good indicator that we
should increase (dma-)ranges - and by extension #address- and
 #size-cells to prevent things from getting lost in translation
(both literally and figuratively). Do so.

Fixes: 7bb7c90e0ac1 ("arm64: dts: qcom: Add Redmi Note 8T")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603141433.MDqfoVHn-lkp@intel.com/
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 arch/arm64/boot/dts/qcom/sm6125.dtsi | 153 ++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 75 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index c84911a98fce..a1a296f90f44 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -374,22 +374,23 @@ smem: smem {
 	};
 
 	soc@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges = <0x00 0x00 0x00 0xffffffff>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0 0 0 0 0x10 0>;
+		dma-ranges = <0 0 0 0 0x10 0>;
 		compatible = "simple-bus";
 
 		tcsr_mutex: hwlock@340000 {
 			compatible = "qcom,tcsr-mutex";
-			reg = <0x00340000 0x20000>;
+			reg = <0x0 0x00340000 0x0 0x20000>;
 			#hwlock-cells = <1>;
 		};
 
 		tlmm: pinctrl@500000 {
 			compatible = "qcom,sm6125-tlmm";
-			reg = <0x00500000 0x400000>,
-			      <0x00900000 0x400000>,
-			      <0x00d00000 0x400000>;
+			reg = <0x0 0x00500000 0x0 0x400000>,
+			      <0x0 0x00900000 0x0 0x400000>,
+			      <0x0 0x00d00000 0x0 0x400000>;
 			reg-names = "west", "south", "east";
 			interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
 			gpio-controller;
@@ -672,7 +673,7 @@ qup_uart4_default: qup-uart4-default-state {
 
 		gcc: clock-controller@1400000 {
 			compatible = "qcom,gcc-sm6125";
-			reg = <0x01400000 0x1f0000>;
+			reg = <0x0 0x01400000 0x0 0x1f0000>;
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 			#power-domain-cells = <1>;
@@ -682,7 +683,7 @@ gcc: clock-controller@1400000 {
 
 		hsusb_phy1: phy@1613000 {
 			compatible = "qcom,msm8996-qusb2-phy";
-			reg = <0x01613000 0x180>;
+			reg = <0x0 0x01613000 0x0 0x180>;
 			#phy-cells = <0>;
 
 			clocks = <&gcc GCC_AHB2PHY_USB_CLK>,
@@ -695,18 +696,18 @@ hsusb_phy1: phy@1613000 {
 
 		rng: rng@1b53000 {
 			compatible = "qcom,prng-ee";
-			reg = <0x01b53000 0x1000>;
+			reg = <0x0 0x01b53000 0x0 0x1000>;
 			clocks = <&gcc GCC_PRNG_AHB_CLK>;
 			clock-names = "core";
 		};
 
 		spmi_bus: spmi@1c40000 {
 			compatible = "qcom,spmi-pmic-arb";
-			reg = <0x01c40000 0x1100>,
-			      <0x01e00000 0x2000000>,
-			      <0x03e00000 0x100000>,
-			      <0x03f00000 0xa0000>,
-			      <0x01c0a000 0x26000>;
+			reg = <0x0 0x01c40000 0x0 0x1100>,
+			      <0x0 0x01e00000 0x0 0x2000000>,
+			      <0x0 0x03e00000 0x0 0x100000>,
+			      <0x0 0x03f00000 0x0 0xa0000>,
+			      <0x0 0x01c0a000 0x0 0x26000>;
 			reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
 			interrupt-names = "periph_irq";
 			interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
@@ -720,12 +721,13 @@ spmi_bus: spmi@1c40000 {
 
 		rpm_msg_ram: sram@45f0000 {
 			compatible = "qcom,rpm-msg-ram";
-			reg = <0x045f0000 0x7000>;
+			reg = <0x0 0x045f0000 0x0 0x7000>;
 		};
 
 		sdhc_1: mmc@4744000 {
 			compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5";
-			reg = <0x04744000 0x1000>, <0x04745000 0x1000>;
+			reg = <0x0 0x04744000 0x0 0x1000>,
+			      <0x0 0x04745000 0x0 0x1000>;
 			reg-names = "hc", "cqhci";
 
 			interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
@@ -752,7 +754,7 @@ sdhc_1: mmc@4744000 {
 
 		sdhc_2: mmc@4784000 {
 			compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5";
-			reg = <0x04784000 0x1000>;
+			reg = <0x0 0x04784000 0x0 0x1000>;
 			reg-names = "hc";
 
 			interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
@@ -780,7 +782,8 @@ sdhc_2: mmc@4784000 {
 
 		ufs_mem_hc: ufshc@4804000 {
 			compatible = "qcom,sm6125-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
-			reg = <0x04804000 0x3000>, <0x04810000 0x8000>;
+			reg = <0x0 0x04804000 0x0 0x3000>,
+			      <0x0 0x04810000 0x0 0x8000>;
 			reg-names = "std", "ice";
 			interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
 
@@ -825,7 +828,7 @@ ufs_mem_hc: ufshc@4804000 {
 
 		ufs_mem_phy: phy@4807000 {
 			compatible = "qcom,sm6125-qmp-ufs-phy";
-			reg = <0x04807000 0xdb8>;
+			reg = <0x0 0x04807000 0x0 0xdb8>;
 
 			clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
 				 <&gcc GCC_UFS_PHY_PHY_AUX_CLK>,
@@ -846,7 +849,7 @@ ufs_mem_phy: phy@4807000 {
 
 		gpi_dma0: dma-controller@4a00000 {
 			compatible = "qcom,sm6125-gpi-dma", "qcom,sdm845-gpi-dma";
-			reg = <0x04a00000 0x60000>;
+			reg = <0x0 0x04a00000 0x0 0x60000>;
 			interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
@@ -864,19 +867,19 @@ gpi_dma0: dma-controller@4a00000 {
 
 		qupv3_id_0: geniqup@4ac0000 {
 			compatible = "qcom,geni-se-qup";
-			reg = <0x04ac0000 0x2000>;
+			reg = <0x0 0x04ac0000 0x0 0x2000>;
 			clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
 				 <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
 			clock-names = "m-ahb", "s-ahb";
 			iommus = <&apps_smmu 0x123 0x0>;
-			#address-cells = <1>;
-			#size-cells = <1>;
+			#address-cells = <2>;
+			#size-cells = <2>;
 			ranges;
 			status = "disabled";
 
 			i2c0: i2c@4a80000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04a80000 0x4000>;
+				reg = <0x0 0x04a80000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
@@ -893,7 +896,7 @@ i2c0: i2c@4a80000 {
 
 			spi0: spi@4a80000 {
 				compatible = "qcom,geni-spi";
-				reg = <0x04a80000 0x4000>;
+				reg = <0x0 0x04a80000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
@@ -910,7 +913,7 @@ spi0: spi@4a80000 {
 
 			i2c1: i2c@4a84000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04a84000 0x4000>;
+				reg = <0x0 0x04a84000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>;
@@ -927,7 +930,7 @@ i2c1: i2c@4a84000 {
 
 			i2c2: i2c@4a88000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04a88000 0x4000>;
+				reg = <0x0 0x04a88000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
@@ -944,7 +947,7 @@ i2c2: i2c@4a88000 {
 
 			spi2: spi@4a88000 {
 				compatible = "qcom,geni-spi";
-				reg = <0x04a88000 0x4000>;
+				reg = <0x0 0x04a88000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
@@ -961,7 +964,7 @@ spi2: spi@4a88000 {
 
 			i2c3: i2c@4a8c000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04a8c000 0x4000>;
+				reg = <0x0 0x04a8c000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>;
@@ -978,7 +981,7 @@ i2c3: i2c@4a8c000 {
 
 			i2c4: i2c@4a90000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04a90000 0x4000>;
+				reg = <0x0 0x04a90000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
@@ -995,7 +998,7 @@ i2c4: i2c@4a90000 {
 
 			uart4: serial@4a90000 {
 				compatible = "qcom,geni-debug-uart";
-				reg = <0x04a90000 0x4000>;
+				reg = <0x0 0x04a90000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
@@ -1007,7 +1010,7 @@ uart4: serial@4a90000 {
 
 		gpi_dma1: dma-controller@4c00000 {
 			compatible = "qcom,sm6125-gpi-dma", "qcom,sdm845-gpi-dma";
-			reg = <0x04c00000 0x60000>;
+			reg = <0x0 0x04c00000 0x0 0x60000>;
 			interrupts = <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
@@ -1025,19 +1028,19 @@ gpi_dma1: dma-controller@4c00000 {
 
 		qupv3_id_1: geniqup@4cc0000 {
 			compatible = "qcom,geni-se-qup";
-			reg = <0x04cc0000 0x2000>;
+			reg = <0x0 0x04cc0000 0x0 0x2000>;
 			clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>,
 				 <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>;
 			clock-names = "m-ahb", "s-ahb";
 			iommus = <&apps_smmu 0x143 0x0>;
-			#address-cells = <1>;
-			#size-cells = <1>;
+			#address-cells = <2>;
+			#size-cells = <2>;
 			ranges;
 			status = "disabled";
 
 			i2c5: i2c@4c80000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04c80000 0x4000>;
+				reg = <0x0 0x04c80000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
@@ -1054,7 +1057,7 @@ i2c5: i2c@4c80000 {
 
 			spi5: spi@4c80000 {
 				compatible = "qcom,geni-spi";
-				reg = <0x04c80000 0x4000>;
+				reg = <0x0 0x04c80000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
@@ -1071,7 +1074,7 @@ spi5: spi@4c80000 {
 
 			i2c6: i2c@4c84000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04c84000 0x4000>;
+				reg = <0x0 0x04c84000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
@@ -1088,7 +1091,7 @@ i2c6: i2c@4c84000 {
 
 			spi6: spi@4c84000 {
 				compatible = "qcom,geni-spi";
-				reg = <0x04c84000 0x4000>;
+				reg = <0x0 0x04c84000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
@@ -1105,7 +1108,7 @@ spi6: spi@4c84000 {
 
 			i2c7: i2c@4c88000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04c88000 0x4000>;
+				reg = <0x0 0x04c88000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
@@ -1122,7 +1125,7 @@ i2c7: i2c@4c88000 {
 
 			i2c8: i2c@4c8c000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04c8c000 0x4000>;
+				reg = <0x0 0x04c8c000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>;
@@ -1139,7 +1142,7 @@ i2c8: i2c@4c8c000 {
 
 			spi8: spi@4c8c000 {
 				compatible = "qcom,geni-spi";
-				reg = <0x04c8c000 0x4000>;
+				reg = <0x0 0x04c8c000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>;
@@ -1156,7 +1159,7 @@ spi8: spi@4c8c000 {
 
 			i2c9: i2c@4c90000 {
 				compatible = "qcom,geni-i2c";
-				reg = <0x04c90000 0x4000>;
+				reg = <0x0 0x04c90000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
@@ -1173,7 +1176,7 @@ i2c9: i2c@4c90000 {
 
 			spi9: spi@4c90000 {
 				compatible = "qcom,geni-spi";
-				reg = <0x04c90000 0x4000>;
+				reg = <0x0 0x04c90000 0x0 0x4000>;
 				clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
 				clock-names = "se";
 				interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
@@ -1191,9 +1194,9 @@ spi9: spi@4c90000 {
 
 		usb3: usb@4ef8800 {
 			compatible = "qcom,sm6125-dwc3", "qcom,dwc3";
-			reg = <0x04ef8800 0x400>;
-			#address-cells = <1>;
-			#size-cells = <1>;
+			reg = <0x0 0x04ef8800 0x0 0x400>;
+			#address-cells = <2>;
+			#size-cells = <2>;
 			ranges;
 
 			clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
@@ -1228,7 +1231,7 @@ usb3: usb@4ef8800 {
 
 			usb3_dwc3: usb@4e00000 {
 				compatible = "snps,dwc3";
-				reg = <0x04e00000 0xcd00>;
+				reg = <0x0 0x04e00000 0x0 0xcd00>;
 				interrupts = <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>;
 				iommus = <&apps_smmu 0x100 0x0>;
 				phys = <&hsusb_phy1>;
@@ -1244,12 +1247,12 @@ usb3_dwc3: usb@4e00000 {
 
 		sram@4690000 {
 			compatible = "qcom,rpm-stats";
-			reg = <0x04690000 0x10000>;
+			reg = <0x0 0x04690000 0x0 0x10000>;
 		};
 
 		mdss: display-subsystem@5e00000 {
 			compatible = "qcom,sm6125-mdss";
-			reg = <0x05e00000 0x1000>;
+			reg = <0x0 0x05e00000 0x0 0x1000>;
 			reg-names = "mdss";
 
 			interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
@@ -1269,16 +1272,16 @@ mdss: display-subsystem@5e00000 {
 
 			iommus = <&apps_smmu 0x400 0x0>;
 
-			#address-cells = <1>;
-			#size-cells = <1>;
+			#address-cells = <2>;
+			#size-cells = <2>;
 			ranges;
 
 			status = "disabled";
 
 			mdss_mdp: display-controller@5e01000 {
 				compatible = "qcom,sm6125-dpu";
-				reg = <0x05e01000 0x83208>,
-				      <0x05eb0000 0x3000>;
+				reg = <0x0 0x05e01000 0x0 0x83208>,
+				      <0x0 0x05eb0000 0x0 0x3000>;
 				reg-names = "mdp", "vbif";
 
 				interrupt-parent = <&mdss>;
@@ -1348,7 +1351,7 @@ opp-400000000 {
 
 			mdss_dsi0: dsi@5e94000 {
 				compatible = "qcom,sm6125-dsi-ctrl", "qcom,mdss-dsi-ctrl";
-				reg = <0x05e94000 0x400>;
+				reg = <0x0 0x05e94000 0x0 0x400>;
 				reg-names = "dsi_ctrl";
 
 				interrupt-parent = <&mdss>;
@@ -1417,9 +1420,9 @@ opp-187500000 {
 
 			mdss_dsi0_phy: phy@5e94400 {
 				compatible = "qcom,sm6125-dsi-phy-14nm";
-				reg = <0x05e94400 0x100>,
-				      <0x05e94500 0x300>,
-				      <0x05e94800 0x188>;
+				reg = <0x0 0x05e94400 0x0 0x100>,
+				      <0x0 0x05e94500 0x0 0x300>,
+				      <0x0 0x05e94800 0x0 0x188>;
 				reg-names = "dsi_phy",
 					    "dsi_phy_lane",
 					    "dsi_pll";
@@ -1441,7 +1444,7 @@ mdss_dsi0_phy: phy@5e94400 {
 
 		dispcc: clock-controller@5f00000 {
 			compatible = "qcom,sm6125-dispcc";
-			reg = <0x05f00000 0x20000>;
+			reg = <0x0 0x05f00000 0x0 0x20000>;
 
 			clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
 				 <&mdss_dsi0_phy DSI_BYTE_PLL_CLK>,
@@ -1470,7 +1473,7 @@ dispcc: clock-controller@5f00000 {
 
 		apps_smmu: iommu@c600000 {
 			compatible = "qcom,sm6125-smmu-500", "qcom,smmu-500", "arm,mmu-500";
-			reg = <0x0c600000 0x80000>;
+			reg = <0x0 0x0c600000 0x0 0x80000>;
 			interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
@@ -1544,74 +1547,74 @@ apps_smmu: iommu@c600000 {
 		apcs_glb: mailbox@f111000 {
 			compatible = "qcom,sm6125-apcs-hmss-global",
 				     "qcom,msm8994-apcs-kpss-global";
-			reg = <0x0f111000 0x1000>;
+			reg = <0x0 0x0f111000 0x0 0x1000>;
 
 			#mbox-cells = <1>;
 		};
 
 		timer@f120000 {
 			compatible = "arm,armv7-timer-mem";
-			#address-cells = <1>;
+			#address-cells = <2>;
 			#size-cells = <1>;
-			ranges;
-			reg = <0x0f120000 0x1000>;
+			reg = <0x0 0x0f120000 0x0 0x1000>;
+			ranges = <0x0 0x0 0x0 0x0 0x20000000>;
 			clock-frequency = <19200000>;
 
 			frame@f121000 {
 				frame-number = <0>;
 				interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
 					     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f121000 0x1000>,
-				      <0x0f122000 0x1000>;
+				reg = <0x0 0x0f121000 0x1000>,
+				      <0x0 0x0f122000 0x1000>;
 			};
 
 			frame@f123000 {
 				frame-number = <1>;
 				interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f123000 0x1000>;
+				reg = <0x0 0x0f123000 0x1000>;
 				status = "disabled";
 			};
 
 			frame@f124000 {
 				frame-number = <2>;
 				interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f124000 0x1000>;
+				reg = <0x0 0x0f124000 0x1000>;
 				status = "disabled";
 			};
 
 			frame@f125000 {
 				frame-number = <3>;
 				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f125000 0x1000>;
+				reg = <0x0 0x0f125000 0x1000>;
 				status = "disabled";
 			};
 
 			frame@f126000 {
 				frame-number = <4>;
 				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f126000 0x1000>;
+				reg = <0x0 0x0f126000 0x1000>;
 				status = "disabled";
 			};
 
 			frame@f127000 {
 				frame-number = <5>;
 				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f127000 0x1000>;
+				reg = <0x0 0x0f127000 0x1000>;
 				status = "disabled";
 			};
 
 			frame@f128000 {
 				frame-number = <6>;
 				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
-				reg = <0x0f128000 0x1000>;
+				reg = <0x0 0x0f128000 0x1000>;
 				status = "disabled";
 			};
 		};
 
 		intc: interrupt-controller@f200000 {
 			compatible = "arm,gic-v3";
-			reg = <0x0f200000 0x20000>,
-			      <0x0f300000 0x100000>;
+			reg = <0x0 0x0f200000 0x0 0x20000>,
+			      <0x0 0x0f300000 0x0 0x100000>;
 			#interrupt-cells = <3>;
 			interrupt-controller;
 			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;

-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 2/7] dt-bindings: clock: qcom,sm6125-dispcc: reference qcom,gcc.yaml
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	kernel test robot
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

Just like most of Qualcomm clock controllers, we can reference common
qcom,gcc.yaml schema to unify the common parts of the binding. This
also adds the '#reset-cells' property which is permitted for the
SM6125 SoC clock controllers, but not listed as a valid property.

Fixes: bb4d28e377cf ("arm64: dts: qcom: sm6125: Add missing MDSS core reset")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603150629.GYoouFwZ-lkp@intel.com/
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 .../devicetree/bindings/clock/qcom,dispcc-sm6125.yaml   | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml
index ef2b1e204430..a177a1934b19 100644
--- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml
@@ -42,12 +42,6 @@ properties:
       - const: cfg_ahb_clk
       - const: gcc_disp_gpll0_div_clk_src
 
-  '#clock-cells':
-    const: 1
-
-  '#power-domain-cells':
-    const: 1
-
   power-domains:
     description:
       A phandle and PM domain specifier for the CX power domain.
@@ -58,18 +52,16 @@ properties:
       A phandle to an OPP node describing the power domain's performance point.
     maxItems: 1
 
-  reg:
-    maxItems: 1
-
 required:
   - compatible
-  - reg
   - clocks
   - clock-names
-  - '#clock-cells'
   - '#power-domain-cells'
 
-additionalProperties: false
+allOf:
+  - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
 
 examples:
   - |
@@ -101,6 +93,7 @@ examples:
       power-domains = <&rpmpd SM6125_VDDCX>;
 
       #clock-cells = <1>;
+      #reset-cells = <1>;
       #power-domain-cells = <1>;
     };
 ...

-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 3/7] arm64: dts: qcom: sm6125-xiaomi-ginkgo: Enable vibrator
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	Dmitry Baryshkov, Konrad Dybcio
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

Enable the vibrator on the PMI632 which is used on this phone.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
index 7eecd9dc3028..88691f1fa3a1 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
@@ -12,6 +12,7 @@
 #include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
 #include "sm6125.dtsi"
 #include "pm6125.dtsi"
+#include "pmi632.dtsi"
 
 /delete-node/ &adsp_pil_mem;
 /delete-node/ &cont_splash_mem;
@@ -115,6 +116,10 @@ &hsusb_phy1 {
 	status = "okay";
 };
 
+&pmi632_vib {
+	status = "okay";
+};
+
 &pon_pwrkey {
 	status = "okay";
 };

-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 4/7] arm64: dts: qcom: sm6125: Enable USB-C port handling
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	Dmitry Baryshkov, Konrad Dybcio
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

Plug in USB-C related bits and pieces to enable USB role switching.
Also, remove dr_mode to enable OTG capability.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 arch/arm64/boot/dts/qcom/sm6125.dtsi | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index a1a296f90f44..d26ca1637330 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -1241,7 +1241,20 @@ usb3_dwc3: usb@4e00000 {
 				snps,dis-u1-entry-quirk;
 				snps,dis-u2-entry-quirk;
 				maximum-speed = "high-speed";
-				dr_mode = "peripheral";
+
+				usb-role-switch;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+
+						usb_dwc3_hs: endpoint {
+						};
+					};
+				};
 			};
 		};
 

-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 5/7] arm64: dts: qcom: sm6125-xiaomi-ginkgo: Add PMI632 Type-C property
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	Konrad Dybcio, Dmitry Baryshkov
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

The USB-C port is used for powering external devices and transfer
data from/to them.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 .../boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
index 88691f1fa3a1..f66ff5f7693b 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
@@ -116,6 +116,33 @@ &hsusb_phy1 {
 	status = "okay";
 };
 
+&pmi632_typec {
+	status = "okay";
+
+	connector {
+		compatible = "usb-c-connector";
+
+		power-role = "dual";
+		data-role = "dual";
+		self-powered;
+
+		typec-power-opmode = "default";
+		pd-disable;
+
+		port {
+			pmi632_hs_in: endpoint {
+				remote-endpoint = <&usb_dwc3_hs>;
+			};
+		};
+	};
+};
+
+&pmi632_vbus {
+	regulator-min-microamp = <500000>;
+	regulator-max-microamp = <1000000>;
+	status = "okay";
+};
+
 &pmi632_vib {
 	status = "okay";
 };
@@ -316,3 +343,7 @@ &uart4 {
 &usb3 {
 	status = "okay";
 };
+
+&usb_dwc3_hs {
+	remote-endpoint = <&pmi632_hs_in>;
+};

-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 6/7] dt-bindings: leds: irled: ir-spi-led: Add new duty-cycle value
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	Krzysztof Kozlowski
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

30 duty cycle for IR transmitter is used in Xiaomi Redmi Note 8 (ginkgo).

Reviewed-by: Sean Young <sean@mess.org>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml b/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
index 72cadebf6e3e..0297bfbb2750 100644
--- a/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
+++ b/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
@@ -25,7 +25,7 @@ properties:
 
   duty-cycle:
     $ref: /schemas/types.yaml#/definitions/uint8
-    enum: [50, 60, 70, 75, 80, 90]
+    enum: [30, 50, 60, 70, 75, 80, 90]
     description:
       Percentage of one period in which the signal is active.
 

-- 
2.53.0


^ permalink raw reply related

* [PATCH v3 7/7] arm64: dts: qcom: sm6125-xiaomi-ginkgo: Add IR transmitter
From: Biswapriyo Nath @ 2026-03-30 10:13 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, Biswapriyo Nath,
	Konrad Dybcio
In-Reply-To: <20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com>

The IR transmitting LED is connected to SPI8 controller.

Reviewed-by: Sean Young <sean@mess.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
---
 .../boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi   | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
index f66ff5f7693b..7d8481173171 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125-xiaomi-ginkgo-common.dtsi
@@ -99,6 +99,10 @@ key-volume-up {
 	};
 };
 
+&gpi_dma1 {
+	status = "okay";
+};
+
 &pm6125_gpios {
 	vol_up_n: vol-up-n-state {
 		pins = "gpio5";
@@ -160,6 +164,10 @@ &qupv3_id_0 {
 	status = "okay";
 };
 
+&qupv3_id_1 {
+	status = "okay";
+};
+
 &rpm_requests {
 	regulators-0 {
 		compatible = "qcom,rpm-pm6125-regulators";
@@ -332,6 +340,18 @@ &sdhc_2 {
 	status = "okay";
 };
 
+&spi8 {
+	status = "okay";
+
+	irled@1 {
+		compatible = "ir-spi-led";
+		reg = <1>;
+
+		duty-cycle = /bits/ 8 <30>;
+		spi-max-frequency = <1000000>;
+	};
+};
+
 &tlmm {
 	gpio-reserved-ranges = <0 4>, <30 4>;
 };

-- 
2.53.0


^ permalink raw reply related

* [PATCH 0/4] ASoC: Add support for GPIOs driven amplifiers
From: Herve Codina @ 2026-03-30 10:16 UTC (permalink / raw)
  To: Herve Codina, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Saravana Kannan,
	Jaroslav Kysela, Takashi Iwai
  Cc: linux-sound, devicetree, linux-kernel, Christophe Leroy,
	Thomas Petazzoni

On some embedded system boards, audio amplifiers are designed using
discrete components such as op-amp, several resistors and switches to
either adjust the gain (switching resistors) or fully switch the
audio signal path (mute and/or bypass features).

Those switches are usually driven by simple GPIOs.

This kind of amplifiers are not handled in ASoC and the fallback is to
let the user-space handle those GPIOs out of the ALSA world.

In order to have those kind of amplifiers fully integrated in the audio
stack, this series introduces the audio-gpio-amp to handle them.

This new ASoC component allows to have the amplifiers seen as ASoC
auxiliarty devices and so it allows to control them through audio mixer
controls.

Best regards,
Hervé

Herve Codina (4):
  of: Introduce of_property_read_s32_index()
  ASoC: dt-bindings: Add support for the GPIOs driven amplifier
  ASoC: codecs: Add support for the GPIOs driven amplifier
  MAINTAINERS: Add the ASoC gpio amplifier entry

 .../bindings/sound/audio-gpio-amp.yaml        | 309 +++++++
 MAINTAINERS                                   |   7 +
 include/linux/of.h                            |   7 +
 sound/soc/codecs/Kconfig                      |  12 +
 sound/soc/codecs/Makefile                     |   2 +
 sound/soc/codecs/audio-gpio-amp.c             | 765 ++++++++++++++++++
 6 files changed, 1102 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/audio-gpio-amp.yaml
 create mode 100644 sound/soc/codecs/audio-gpio-amp.c

-- 
2.53.0


^ permalink raw reply

* [PATCH 1/4] of: Introduce of_property_read_s32_index()
From: Herve Codina @ 2026-03-30 10:16 UTC (permalink / raw)
  To: Herve Codina, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Saravana Kannan,
	Jaroslav Kysela, Takashi Iwai
  Cc: linux-sound, devicetree, linux-kernel, Christophe Leroy,
	Thomas Petazzoni
In-Reply-To: <20260330101610.57942-1-herve.codina@bootlin.com>

Signed integers can be read from single value properties using
of_property_read_s32() but nothing exist to read signed integers
from multi-value properties.

Fix this lack adding of_property_read_s32_index().

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 include/linux/of.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/of.h b/include/linux/of.h
index be6ec4916adf..526c1ee819cd 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1457,6 +1457,13 @@ static inline int of_property_read_s32(const struct device_node *np,
 	return of_property_read_u32(np, propname, (u32*) out_value);
 }
 
+static inline int of_property_read_s32_index(const struct device_node *np,
+					     const char *propname, u32 index,
+					     s32 *out_value)
+{
+	return of_property_read_u32_index(np, propname, index, (u32 *)out_value);
+}
+
 #define of_for_each_phandle(it, err, np, ln, cn, cc)			\
 	for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)),	\
 	     err = of_phandle_iterator_next(it);			\
-- 
2.53.0


^ permalink raw reply related

* [PATCH 2/4] ASoC: dt-bindings: Add support for the GPIOs driven amplifier
From: Herve Codina @ 2026-03-30 10:16 UTC (permalink / raw)
  To: Herve Codina, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Saravana Kannan,
	Jaroslav Kysela, Takashi Iwai
  Cc: linux-sound, devicetree, linux-kernel, Christophe Leroy,
	Thomas Petazzoni
In-Reply-To: <20260330101610.57942-1-herve.codina@bootlin.com>

Some amplifiers based on analog switches and op-amps can be present in
the audio path and can be driven by GPIOs in order to control their gain
value, their mute and/or bypass functions.

Those components needs to be viewed as audio components in order to be
fully integrated in the audio path.

audio-gpio-amplifier allows to consider these GPIO driven amplifiers as
auxiliary audio devices.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 .../bindings/sound/audio-gpio-amp.yaml        | 309 ++++++++++++++++++
 1 file changed, 309 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/audio-gpio-amp.yaml

diff --git a/Documentation/devicetree/bindings/sound/audio-gpio-amp.yaml b/Documentation/devicetree/bindings/sound/audio-gpio-amp.yaml
new file mode 100644
index 000000000000..15dc898f8574
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/audio-gpio-amp.yaml
@@ -0,0 +1,309 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/audio-gpio-amp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Audio amplifier driven by GPIOs
+
+maintainers:
+  - Herve Codina <herve.codina@bootlin.com>
+
+description: |
+  Audio GPIO amplifiers are driven by GPIO in order to control the gain value
+  of the amplifier, its mute function and/or its bypass function.
+
+  Those amplifiers are based on discrete components (analog switches, op-amps
+  and more) where some of them, mostly analog switches, are controlled by GPIOs
+  to adjust the gain value of the whole amplifier and/or to control
+  the mute and/or bypass function.
+
+  For instance, the following piece of hardware is a GPIO amplifier
+
+                                         +5VA
+                                           ^
+                                        |\ |
+                                        | \
+        Vin >---------------------------|+ \
+                                        |   +-------+-----> Vout
+                .--\/\/\/--+------------|- /        |
+                |          |            | /         |
+                v          |            |/ |        |
+               GND         o               v        |
+                            \             GND       |
+       gpio >----------->    \                      |
+                         o    o                     |
+                         |    |                     |
+                         |    '--\/\/\/--.          |
+                         |               +--\/\/\/--'
+                         '---------------'
+
+  A GPIO driven amplifier can work in several mode depending on the electronic
+  design.
+    - points defined:
+        The values of GPIOs used to control gain set a specific gain value
+        without any specific relationship between each value. For instance,
+        using 2 GPIOS:
+          0b00 <-> -10.0 dB
+          0b01 <-> +3.0 dB
+          0b10 <-> 0 dB
+          0b11 <-> +6.0 dB
+
+        This can be described using the gain-points property.
+
+    - range defined:
+        The values of GPIOs used to control gain set a specific gain value
+        following a linear dB range from a minimum dB value to a maximum dB
+        value. For instance, using 2 GPIOS:
+          0b00 <-> -3.0 dB
+          0b01 <-> 0 db
+          0b10 <-> +3.0 dB
+          0b11 <-> +6.0 dB
+
+        This can be described using the gain-range property.
+
+    - labels defined:
+        Some electronic design are not meant to a specific dB gain value. In
+        that case it is relevant to use labels to describe them. For instance,
+        using 2 GPIOS:
+          0b00 <-> Low boost
+          0b01 <-> Middle boost
+          0b10 <-> High boost
+          0b11 <-> Max boost
+
+        This can be described using the gain-labels property
+
+properties:
+  compatible:
+    const: audio-gpio-amp
+
+  vdd-supply:
+    description: Main power supply of the amplifier
+
+  vddio-supply:
+    description: Power supply related to the control path
+
+  vdda1-supply:
+    description: Analog power supply
+
+  vdda2-supply:
+    description: Additional analog power supply
+
+  mute-gpios:
+    description: GPIO to control the mute function
+    maxItems: 1
+
+  bypass-gpios:
+    description: GPIO to control the bypass function
+    maxItems: 1
+
+  gain-gpios:
+    description: |
+      GPIOs to control the amplifier gain
+
+      The gain value is computed from GPIOs value from 0 to 2^N-1 with N the
+      number of GPIO described. The first GPIO described is the lsb of the gain
+      value.
+
+      For instance assuming 2 gpios
+         gain-gpios = <&gpio1 GPIO_ACTIVE_HIGH> <&gpio2 GPIO_ACTIVE_HIGH>;
+      The gain value will be the following:
+
+          gpio1 | gpio2 | gain
+          ------+-------+-----
+            0   |    0  | 0b00 -> 0
+            1   |    0  | 0b01 -> 1
+            0   |    1  | 0b10 -> 2
+            1   |    1  | 0b11 -> 3
+          ------+-------+-----
+
+      Note: The gain value, bits set to 1 or 0, indicate the state active (bit
+            set) or the state inactive (bit unset) of the related GPIO. The
+            physical voltage corresponding to this active/inactive state is
+            given by the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags.
+
+    minItems: 1
+    maxItems: 32
+
+  gain-points:
+    $ref: /schemas/types.yaml#/definitions/int32-matrix
+    items:
+      items:
+        - description: The GPIOs value
+        - description: The related amplifier gain in 0.01 dB unit
+    minItems: 2
+    description: |
+      List of the GPIOs value / Gain value in dB pair defining the gain
+      set on each GPIOs value.
+
+      With 2 GPIOs controlling the gain, GPIOs value can be 0, 1, 2 and 3.
+      Assuming that GPIOs values set the hardware gains according to the
+      following table:
+
+         GPIOs | Hardware
+         value | amplification
+         ------+--------------
+           0   | -10.0 dB
+           1   | +3.0 dB
+           2   | 0 dB
+           3   | +6.0 dB
+         ------+--------------
+
+      The description using gain points can be:
+        gain-points = <0 (-1000)>, <1 300>, <2 0>, <3 600>;
+
+  gain-range:
+    $ref: /schemas/types.yaml#/definitions/int32-array
+    items:
+      - description: Gain in 0.01 dB unit when all GPIOs are inactive
+      - description: Gain in 0.01 dB unit when all GPIOs are active
+    description: |
+      Gains (in 0.01 dB unit) set by the extremum (minimal and maximum) value
+      of GPIOs. The following formula must be satisfied.
+
+               gain-range[1] - gain-range[0]
+      Gain  = ------------------------------- x GPIO_value + gain-range[0]
+                        2^N - 1
+
+      With N, the number of GPIOs used to control the gain and Gain computed in
+      0.01 dB unit.
+
+      With 2 GPIOs controlling the gain, GPIOs value can be 0, 1, 2 and 3.
+      Assuming that gain value set the hardware according to the following
+      table:
+
+         GPIOs | Hardware 1    | Hardware 2
+         value | amplification | amplification
+         ------+---------------+---------------
+           0   | -3.0 dB       |  +10.0 dB
+           1   | 0 dB          |  +5.0 dB
+           2   | +3.0 dB       |  0 dB
+           3   | +6.0 dB       |  -5.0 dB
+         ------+---------------+---------------
+
+      The description for hardware 1 using a gain range can be:
+        gain-range = <(-300) 600>;
+
+      The description for hardware 2 using a gain range can be:
+        gain-range = <1000 (-500)>;
+
+  gain-labels:
+    $ref: /schemas/types.yaml#/definitions/string-array
+    description: |
+      List of the gain labels attached to the combination of GPIOs controlling
+      the gain. The first label is related to the gain value 0, the second label
+      is related to the gain value 1 and so on.
+
+      With 2 GPIOs controlling the gain, GPIOs value can be 0, 1, 2 and 3.
+      Assuming that gain value set the hardware according to the following
+      table:
+
+         GPIOs | Hardware
+         value | amplification
+         ------+--------------
+           0   | Low
+           1   | Middle
+           2   | High
+           3   | Max
+         ------+--------------
+
+      The description using gain labels can be:
+        gain-labels = "Low", "Middle", "High", "Max";
+
+dependencies:
+  gain-points: [ gain-gpios ]
+  gain-range: [ gain-gpios ]
+  gain-labels: [ gain-gpios ]
+
+required:
+  - compatible
+  - vdd-supply
+
+anyOf:
+  - required:
+      - gain-gpios
+  - required:
+      - mute-gpios
+  - required:
+      - bypass-gpios
+
+allOf:
+  - $ref: dai-common.yaml#
+  - if:
+      required:
+        - gain-points
+    then:
+      properties:
+        gain-range: false
+        gain-labels: false
+  - if:
+      required:
+        - gain-range
+    then:
+      properties:
+        gain-points: false
+        gain-labels: false
+  - if:
+      required:
+        - gain-labels
+    then:
+      properties:
+        gain-points: false
+        gain-range: false
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    /* Gain controlled by gpios */
+    amplifier0 {
+        compatible = "audio-gpio-amp";
+        vdd-supply = <&regulator>;
+        gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>;
+    };
+
+    /* Gain controlled by gpio using range */
+    amplifier1 {
+        compatible = "audio-gpio-amp";
+        vdd-supply = <&regulator>;
+        gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>;
+        gain-range = <(-300) 600>;
+    };
+
+    /* Gain controlled by gpio using points */
+    amplifier2 {
+        compatible = "audio-gpio-amp";
+        vdd-supply = <&regulator>;
+        gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>;
+        gain-points = <0 (-1000)>, <1 300>, <2 0>, <3 600>;
+    };
+
+    /* Gain controlled by gpio with labels */
+    amplifier3 {
+        compatible = "audio-gpio-amp";
+        vdd-supply = <&regulator>;
+        gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+        gain-labels = "Low", "High";
+    };
+
+    /* A mutable amplifier without any gain control */
+    amplifier4 {
+        compatible = "audio-gpio-amp";
+        vdd-supply = <&regulator>;
+        mute-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+    };
+
+    /*  Several supplies, gain controlled using range, mute and bypass */
+    amplifier5 {
+        compatible = "audio-gpio-amp";
+        vdd-supply = <&regulator>;
+        vddio-supply = <&regulator1>;
+        vdda1-supply = <&regulator2>;
+        gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>;
+        gain-range = <(-300) 600>;
+        mute-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
+        bypass-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
+    };
+...
-- 
2.53.0


^ permalink raw reply related

* [PATCH 3/4] ASoC: codecs: Add support for the GPIOs driven amplifier
From: Herve Codina @ 2026-03-30 10:16 UTC (permalink / raw)
  To: Herve Codina, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Saravana Kannan,
	Jaroslav Kysela, Takashi Iwai
  Cc: linux-sound, devicetree, linux-kernel, Christophe Leroy,
	Thomas Petazzoni
In-Reply-To: <20260330101610.57942-1-herve.codina@bootlin.com>

Some amplifiers driven by GPIOs can be present in the audio path.

In order to be fully integrated in the audio path and to have audio
mixer items available to control those amplifiers, an audio component
is needed.

This support allows to handle those GPIO driven amplifiers as auxiliary
audio devices and so control them using audio mixer controls.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 sound/soc/codecs/Kconfig          |  12 +
 sound/soc/codecs/Makefile         |   2 +
 sound/soc/codecs/audio-gpio-amp.c | 765 ++++++++++++++++++++++++++++++
 3 files changed, 779 insertions(+)
 create mode 100644 sound/soc/codecs/audio-gpio-amp.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index adb3fb923be3..9c51519d6eea 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -52,6 +52,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_AK5558
 	imply SND_SOC_ALC5623
 	imply SND_SOC_ALC5632
+	imply SND_SOC_AUDIO_GPIO_AMP
 	imply SND_SOC_AUDIO_IIO_AUX
 	imply SND_SOC_AW8738
 	imply SND_SOC_AW87390
@@ -648,6 +649,17 @@ config SND_SOC_ALC5632
 	tristate
 	depends on I2C
 
+config SND_SOC_AUDIO_GPIO_AMP
+	tristate "Audio GPIO Amplifier"
+	select GPIOLIB
+	help
+	  Enable support for GPIO amplifier.
+	  This allows to have an amplifier driven by GPIOs in the audio path and
+	  controlled using mixer controls.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-soc-audio-gpio-amp.
+
 config SND_SOC_AUDIO_IIO_AUX
 	tristate "Audio IIO Auxiliary device"
 	depends on IIO
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 3ddee5298721..e1794a3368ab 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -423,6 +423,7 @@ snd-soc-wsa883x-y := wsa883x.o
 snd-soc-wsa884x-y := wsa884x.o
 snd-soc-zl38060-y := zl38060.o
 # Amp
+snd-soc-audio-gpio-amp-y := audio-gpio-amp.o
 snd-soc-max9877-y := max9877.o
 snd-soc-max98504-y := max98504.o
 snd-soc-simple-amplifier-y := simple-amplifier.o
@@ -869,6 +870,7 @@ obj-$(CONFIG_SND_SOC_WSA884X)	+= snd-soc-wsa884x.o
 obj-$(CONFIG_SND_SOC_ZL38060)	+= snd-soc-zl38060.o
 
 # Amp
+obj-$(CONFIG_SND_SOC_AUDIO_GPIO_AMP)	+= snd-soc-audio-gpio-amp.o
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
 obj-$(CONFIG_SND_SOC_MAX98504)	+= snd-soc-max98504.o
 obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER)	+= snd-soc-simple-amplifier.o
diff --git a/sound/soc/codecs/audio-gpio-amp.c b/sound/soc/codecs/audio-gpio-amp.c
new file mode 100644
index 000000000000..053501cfa5d6
--- /dev/null
+++ b/sound/soc/codecs/audio-gpio-amp.c
@@ -0,0 +1,765 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// GPIOs controlled amplifier ALSA SoC driver
+//
+// Copyright 2026 CS GROUP France
+//
+// Author: Herve Codina <herve.codina@bootlin.com>
+
+#include <linux/bitmap.h>
+#include <linux/gpio/consumer.h>
+#include <linux/minmax.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+struct audio_gpio_single {
+	struct gpio_desc *gpio;
+	bool is_inverted;
+	int kctrl_val;
+	const char *control_name;
+};
+
+struct audio_gpio_point {
+	u32 gpio_val;
+	int gain_db;
+};
+
+struct audio_gpio_points {
+	unsigned int nb_points;
+	struct audio_gpio_point *tab_points;
+};
+
+struct audio_gpio_range {
+	int min_db;
+	int max_db;
+};
+
+struct audio_gpio_labels {
+	unsigned int nb_labels;
+	const char **tab_labels;
+};
+
+enum audio_gpio_mode {
+	AUDIO_GPIO_MODE_NONE,
+	AUDIO_GPIO_MODE_RANGE,
+	AUDIO_GPIO_MODE_LABELS,
+	AUDIO_GPIO_MODE_POINTS,
+};
+
+struct audio_gpio_multi {
+	struct gpio_descs *gpios;
+	bool is_inverted;
+	u32 kctrl_val;
+	u32 kctrl_max;
+	const char *control_name;
+	unsigned int *tlv_array;
+	enum audio_gpio_mode mode;
+	union {
+		struct audio_gpio_range range;
+		struct audio_gpio_points points;
+		struct audio_gpio_labels labels;
+	};
+};
+
+struct audio_gpio_amp {
+	struct audio_gpio_single mute;
+	struct audio_gpio_single bypass;
+	struct audio_gpio_multi gain;
+};
+
+static const struct snd_soc_dapm_widget audio_gpio_amp_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("IN"),
+	SND_SOC_DAPM_OUTPUT("OUT"),
+	SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0),
+};
+
+static const struct snd_soc_dapm_route audio_gpio_amp_dapm_routes[] = {
+	{ "PGA", NULL, "IN" },
+	{ "PGA", NULL, "vdd" },
+	{ "OUT", NULL, "PGA" },
+};
+
+static int audio_gpio_amp_single_kctrl_write_gpio(struct audio_gpio_single *single,
+						  int kctrl_val)
+{
+	int gpio_val;
+
+	gpio_val = single->is_inverted ? !kctrl_val : kctrl_val;
+
+	return gpiod_set_value_cansleep(single->gpio, gpio_val);
+}
+
+static int audio_gpio_amp_single_kctrl_info(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	return 0;
+}
+
+static int audio_gpio_amp_single_kctrl_get(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct audio_gpio_single *single = (struct audio_gpio_single *)kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = single->kctrl_val;
+
+	return 0;
+}
+
+static int audio_gpio_amp_single_kctrl_put(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct audio_gpio_single *single = (struct audio_gpio_single *)kcontrol->private_value;
+	int kctrl_val;
+	int err;
+
+	kctrl_val = ucontrol->value.integer.value[0];
+
+	if (kctrl_val == single->kctrl_val)
+		return 0;
+
+	err = audio_gpio_amp_single_kctrl_write_gpio(single, kctrl_val);
+	if (err)
+		return err;
+
+	single->kctrl_val = kctrl_val;
+
+	return 1; /* The value changed */
+}
+
+static int audio_gpio_amp_single_add_kcontrol(struct snd_soc_component *component,
+					      struct audio_gpio_single *single)
+{
+	struct snd_kcontrol_new control = {
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = single->control_name,
+		.info = audio_gpio_amp_single_kctrl_info,
+		.get = audio_gpio_amp_single_kctrl_get,
+		.put = audio_gpio_amp_single_kctrl_put,
+		.private_value = (unsigned long)single,
+	};
+	int ret;
+
+	/* Be consistent between single->kctrl_val value and the GPIO value */
+	ret = audio_gpio_amp_single_kctrl_write_gpio(single, single->kctrl_val);
+	if (ret)
+		return ret;
+
+	return snd_soc_add_component_controls(component, &control, 1);
+}
+
+static int audio_gpio_amp_multi_kctrl_write_gpios(struct audio_gpio_multi *multi,
+						  u32 kctrl_val)
+{
+	DECLARE_BITMAP(bm, 32);
+	u32 gpio_val;
+
+	if (multi->mode == AUDIO_GPIO_MODE_POINTS) {
+		if (kctrl_val >= multi->points.nb_points)
+			return -EINVAL;
+
+		gpio_val = multi->points.tab_points[kctrl_val].gpio_val;
+	} else {
+		if (kctrl_val > multi->kctrl_max)
+			return -EINVAL;
+
+		gpio_val = multi->is_inverted ?
+				multi->kctrl_max - kctrl_val :
+				kctrl_val;
+	}
+
+	bitmap_from_arr32(bm, &gpio_val, multi->gpios->ndescs);
+
+	return gpiod_multi_set_value_cansleep(multi->gpios, bm);
+}
+
+static int audio_gpio_amp_multi_kctrl_int_info(struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_info *uinfo)
+{
+	struct audio_gpio_multi *multi = (struct audio_gpio_multi *)kcontrol->private_value;
+
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	if (multi->mode == AUDIO_GPIO_MODE_POINTS)
+		uinfo->value.integer.max = multi->points.nb_points - 1;
+	else
+		uinfo->value.integer.max = multi->kctrl_max;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	return 0;
+}
+
+static int audio_gpio_amp_multi_kctrl_int_get(struct snd_kcontrol *kcontrol,
+					      struct snd_ctl_elem_value *ucontrol)
+{
+	struct audio_gpio_multi *multi = (struct audio_gpio_multi *)kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = multi->kctrl_val;
+	return 0;
+}
+
+static int audio_gpio_amp_multi_kctrl_int_put(struct snd_kcontrol *kcontrol,
+					      struct snd_ctl_elem_value *ucontrol)
+{
+	struct audio_gpio_multi *multi = (struct audio_gpio_multi *)kcontrol->private_value;
+	u32 kctrl_val;
+	int ret;
+
+	kctrl_val = ucontrol->value.integer.value[0];
+
+	if (kctrl_val == multi->kctrl_val)
+		return 0;
+
+	ret = audio_gpio_amp_multi_kctrl_write_gpios(multi, kctrl_val);
+	if (ret)
+		return ret;
+
+	multi->kctrl_val = kctrl_val;
+
+	return 1; /* The value changed */
+}
+
+static int audio_gpio_amp_multi_kctrl_enum_info(struct snd_kcontrol *kcontrol,
+						struct snd_ctl_elem_info *uinfo)
+{
+	struct audio_gpio_multi *multi = (struct audio_gpio_multi *)kcontrol->private_value;
+
+	return snd_ctl_enum_info(uinfo, 1, multi->labels.nb_labels,
+				 multi->labels.tab_labels);
+}
+
+static int audio_gpio_amp_multi_kctrl_enum_get(struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_value *ucontrol)
+{
+	struct audio_gpio_multi *multi = (struct audio_gpio_multi *)kcontrol->private_value;
+
+	ucontrol->value.enumerated.item[0] = multi->kctrl_val;
+	return 0;
+}
+
+static int audio_gpio_amp_multi_kctrl_enum_put(struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_value *ucontrol)
+{
+	struct audio_gpio_multi *multi = (struct audio_gpio_multi *)kcontrol->private_value;
+	u32 kctrl_val;
+	int ret;
+
+	kctrl_val = ucontrol->value.enumerated.item[0];
+
+	if (kctrl_val == multi->kctrl_val)
+		return 0;
+
+	ret = audio_gpio_amp_multi_kctrl_write_gpios(multi, kctrl_val);
+	if (ret)
+		return ret;
+
+	multi->kctrl_val = kctrl_val;
+
+	return 1; /* The value changed */
+}
+
+static int *audio_gpio_amp_alloc_tlv_range(const struct audio_gpio_range *range)
+{
+	DECLARE_TLV_DB_MINMAX(tmp, range->min_db, range->max_db);
+
+	return kmemdup(tmp, sizeof(tmp), GFP_KERNEL);
+}
+
+static int *audio_gpio_amp_alloc_tlv_points(struct audio_gpio_points *points)
+{
+	unsigned int *tlv;
+	unsigned int *t;
+	unsigned int i;
+
+	tlv = kzalloc_objs(*tlv, 2 + points->nb_points * 6, GFP_KERNEL);
+	if (!tlv)
+		return NULL;
+
+	t = tlv;
+
+	/* Fill first TLV */
+	*t++ = SNDRV_CTL_TLVT_DB_RANGE; /* Tag */
+	*t++ = points->nb_points * 6 * sizeof(*tlv); /* Len */
+	/* points are sorted from lower to higher value */
+	for (i = 0; i < points->nb_points; i++) {
+		/* Fill item i */
+		*t++ = i;  /* min */
+		*t++ = i;  /* max */
+		*t++ = SNDRV_CTL_TLVT_DB_MINMAX; /* Tag */
+		*t++ = 2 * sizeof(*tlv); /* Len */
+		*t++ = points->tab_points[i].gain_db; /* min_dB */
+		*t++ = points->tab_points[i].gain_db; /* max_dB */
+	}
+
+	return tlv;
+}
+
+static int audio_gpio_amp_multi_add_kcontrol(struct snd_soc_component *component,
+					     struct audio_gpio_multi *multi)
+{
+	struct snd_kcontrol_new control = {
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = multi->control_name,
+		.info = audio_gpio_amp_multi_kctrl_int_info,
+		.get = audio_gpio_amp_multi_kctrl_int_get,
+		.put = audio_gpio_amp_multi_kctrl_int_put,
+		.private_value = (unsigned long)multi,
+	};
+	int ret;
+
+	switch (multi->mode) {
+	case AUDIO_GPIO_MODE_RANGE:
+		multi->tlv_array = audio_gpio_amp_alloc_tlv_range(&multi->range);
+		if (!multi->tlv_array)
+			return -ENOMEM;
+
+		control.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+				 SNDRV_CTL_ELEM_ACCESS_READWRITE;
+		control.tlv.p = multi->tlv_array;
+		break;
+
+	case AUDIO_GPIO_MODE_POINTS:
+		multi->tlv_array = audio_gpio_amp_alloc_tlv_points(&multi->points);
+		if (!multi->tlv_array)
+			return -ENOMEM;
+
+		control.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+				 SNDRV_CTL_ELEM_ACCESS_READWRITE;
+		control.tlv.p = multi->tlv_array;
+		break;
+
+	case AUDIO_GPIO_MODE_LABELS:
+		/* Use enumerated values */
+		control.info = audio_gpio_amp_multi_kctrl_enum_info;
+		control.get = audio_gpio_amp_multi_kctrl_enum_get;
+		control.put = audio_gpio_amp_multi_kctrl_enum_put;
+		break;
+
+	case AUDIO_GPIO_MODE_NONE:
+		/* Already set control configuration is enough */
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* Be consistent between multi->kctrl_val value and the GPIOs value */
+	ret = audio_gpio_amp_multi_kctrl_write_gpios(multi, multi->kctrl_val);
+	if (ret)
+		return ret;
+
+	return snd_soc_add_component_controls(component, &control, 1);
+}
+
+struct audio_gpio_amp_supply {
+	const char *prop_name;
+	const struct snd_soc_dapm_widget dapm_widget;
+	const struct snd_soc_dapm_route dapm_route;
+};
+
+static const struct audio_gpio_amp_supply audio_gpio_amp_supplies[] = {
+	{
+		.prop_name = "vddio-supply",
+		.dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vddio", 0, 0),
+		.dapm_route = { "PGA", NULL, "vddio" },
+	}, {
+		.prop_name = "vdda1-supply",
+		.dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda1", 0, 0),
+		.dapm_route = { "PGA", NULL, "vdda1" },
+	}, {
+		.prop_name = "vdda2-supply",
+		.dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda2", 0, 0),
+		.dapm_route = { "PGA", NULL, "vdda2" },
+	},
+	{ /* End of list */}
+};
+
+static int audio_gpio_amp_add_power_supplies(struct snd_soc_component *component)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+	const struct audio_gpio_amp_supply *supply;
+	struct device *dev = component->dev;
+	int ret;
+
+	supply = audio_gpio_amp_supplies;
+	do {
+		if (!of_property_present(dev->of_node, supply->prop_name))
+			continue;
+
+		ret = snd_soc_dapm_new_controls(dapm, &supply->dapm_widget, 1);
+		if (ret) {
+			dev_err(dev, "Failed to add control for '%s' (%d)\n",
+				supply->prop_name, ret);
+			return ret;
+		}
+		ret = snd_soc_dapm_add_routes(dapm, &supply->dapm_route, 1);
+		if (ret) {
+			dev_err(dev, "Failed to add route for '%s' (%d)\n",
+				supply->prop_name, ret);
+			return ret;
+		}
+	} while ((++supply)->prop_name);
+
+	return 0;
+}
+
+static int audio_gpio_amp_component_probe(struct snd_soc_component *component)
+{
+	struct audio_gpio_amp *gpio_amp = snd_soc_component_get_drvdata(component);
+	int ret;
+
+	ret = audio_gpio_amp_add_power_supplies(component);
+	if (ret)
+		return ret;
+
+	if (gpio_amp->mute.gpio) {
+		/*
+		 * The name of the GPIO used is mute. According to this name, 1
+		 * means muted and 0 means un-muted.
+		 *
+		 * An inversion is expected by ALSA. Indeed from ALSA point of
+		 * view, 1 means 'on' (un-muted) and 0 means 'off' (muted).
+		 */
+		gpio_amp->mute.is_inverted = true;
+		gpio_amp->mute.kctrl_val = 1; /* Un-muted */
+		ret = audio_gpio_amp_single_add_kcontrol(component, &gpio_amp->mute);
+		if (ret)
+			return ret;
+	}
+
+	if (gpio_amp->bypass.gpio) {
+		ret = audio_gpio_amp_single_add_kcontrol(component, &gpio_amp->bypass);
+		if (ret)
+			return ret;
+	}
+
+	if (gpio_amp->gain.gpios) {
+		ret = audio_gpio_amp_multi_add_kcontrol(component, &gpio_amp->gain);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void audio_gpio_amp_component_remove(struct snd_soc_component *component)
+{
+	struct audio_gpio_amp *gpio_amp = snd_soc_component_get_drvdata(component);
+
+	kfree(gpio_amp->gain.tlv_array);
+	gpio_amp->gain.tlv_array = NULL;
+}
+
+static const struct snd_soc_component_driver audio_gpio_amp_component_driver = {
+	.dapm_widgets		= audio_gpio_amp_dapm_widgets,
+	.num_dapm_widgets	= ARRAY_SIZE(audio_gpio_amp_dapm_widgets),
+	.dapm_routes		= audio_gpio_amp_dapm_routes,
+	.num_dapm_routes	= ARRAY_SIZE(audio_gpio_amp_dapm_routes),
+	.probe = audio_gpio_amp_component_probe,
+	.remove = audio_gpio_amp_component_remove,
+};
+
+static int audio_gpio_amp_parse_labels(struct device *dev,
+				       struct audio_gpio_multi *multi,
+				       const char *labels_property)
+{
+	struct audio_gpio_labels *labels = &multi->labels;
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	ret = of_property_count_strings(np, labels_property);
+	if (ret <= 0)
+		return ret;
+
+	labels->nb_labels = ret;
+	if (labels->nb_labels > (1 << multi->gpios->ndescs))
+		return -EINVAL;
+
+	labels->tab_labels = devm_kcalloc(dev, labels->nb_labels,
+					  sizeof(*labels->tab_labels),
+					  GFP_KERNEL);
+	if (!labels->tab_labels)
+		return -ENOMEM;
+
+	multi->kctrl_max = labels->nb_labels - 1;
+	multi->kctrl_val = 0;
+	multi->is_inverted = false;
+
+	return of_property_read_string_array(np, labels_property, labels->tab_labels,
+					     labels->nb_labels);
+}
+
+static int audio_gpio_amp_parse_range(struct device *dev,
+				      struct audio_gpio_multi *multi,
+				      const char *range_property)
+{
+	struct audio_gpio_range *range = &multi->range;
+	struct device_node *np = dev->of_node;
+	s32 tmp;
+	int ret;
+
+	ret = of_property_read_s32_index(np, range_property, 0, &tmp);
+	if (ret)
+		return ret;
+	range->min_db = tmp;
+
+	ret = of_property_read_s32_index(np, range_property, 1, &tmp);
+	if (ret)
+		return ret;
+	range->max_db = tmp;
+
+	multi->kctrl_max = (1 << multi->gpios->ndescs) - 1;
+	multi->kctrl_val = 0;
+	multi->is_inverted = false;
+
+	if (range->min_db > range->max_db) {
+		/* Invert range */
+		swap(range->min_db, range->max_db);
+		multi->is_inverted = 1;
+
+		/*
+		 * When the range is inverted, choose to have the initial
+		 * amplification set to max_db (i.e. all GPIOs inactive).
+		 */
+		multi->kctrl_val = multi->kctrl_max;
+	}
+
+	return 0;
+}
+
+static int audio_gpio_amp_cmp_points(const void *a, const void *b)
+{
+	const struct audio_gpio_point *a_point = a;
+	const struct audio_gpio_point *b_point = b;
+
+	return a_point->gain_db - b_point->gain_db;
+}
+
+static int audio_gpio_amp_parse_points(struct device *dev,
+				       struct audio_gpio_multi *multi,
+				       const char *points_property)
+{
+	struct audio_gpio_points *points = &multi->points;
+	struct device_node *np = dev->of_node;
+	struct audio_gpio_point first_point;
+	unsigned int max_gpio_val;
+	unsigned int i;
+	int ret;
+	u32 u;
+	s32 s;
+
+	max_gpio_val = (1 << multi->gpios->ndescs) - 1;
+
+	ret = of_property_count_u32_elems(np, points_property);
+	if (ret <= 0)
+		return ret;
+
+	if (ret % 2)
+		return -EINVAL;
+
+	points->nb_points = ret / 2;
+	if (points->nb_points > max_gpio_val + 1)
+		return -EINVAL;
+
+	points->tab_points = devm_kcalloc(dev, points->nb_points,
+					  sizeof(*points->tab_points),
+					  GFP_KERNEL);
+	if (!points->tab_points)
+		return -ENOMEM;
+
+	for (i = 0; i < points->nb_points; i++) {
+		/* Gpio value */
+		ret = of_property_read_u32_index(np, points_property,
+						 i * 2, &u);
+		if (ret)
+			return ret;
+		if (u > max_gpio_val)
+			return -EINVAL;
+
+		points->tab_points[i].gpio_val = u;
+
+		/* Gain value */
+		ret = of_property_read_s32_index(np, points_property,
+						 i * 2 + 1, &s);
+		if (ret)
+			return ret;
+
+		points->tab_points[i].gain_db = s;
+	}
+
+	first_point = points->tab_points[0];
+
+	/* Sort the tab_point array by gain_db value */
+	sort(points->tab_points, points->nb_points, sizeof(*points->tab_points),
+	     audio_gpio_amp_cmp_points, NULL);
+
+	multi->kctrl_max = points->nb_points - 1;
+	multi->is_inverted = false;
+
+	/*
+	 * multi->kctrl_val is the index in tab_points.
+	 *
+	 * Choose to have the initial amplification value set to the first item
+	 * available in the tab_points array before sorting.
+	 *
+	 * This first point before sorting has been identified. Search for it in
+	 * the sorted array in order to set the multi->kctrl_val initial value.
+	 */
+	for (i = 0; i < points->nb_points; i++) {
+		if (points->tab_points[i].gpio_val == first_point.gpio_val &&
+		    points->tab_points[i].gain_db == first_point.gain_db) {
+			multi->kctrl_val = i;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int audio_gpio_amp_parse_multi_gpio(struct device *dev,
+					   struct audio_gpio_multi *multi,
+					   const char *gpios_property,
+					   const char *range_property,
+					   const char *points_property,
+					   const char *labels_property)
+{
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	/* Start with the value 0 (GPIO inactive). Can be changed later */
+	multi->is_inverted = false;
+	multi->kctrl_val = 0;
+	multi->gpios = devm_gpiod_get_array_optional(dev, gpios_property, GPIOD_OUT_LOW);
+	if (IS_ERR(multi->gpios))
+		return dev_err_probe(dev, PTR_ERR(multi->gpios),
+				     "Failed to get '%s' gpios\n",
+				     gpios_property);
+	if (!multi->gpios)
+		return 0;
+
+	if (multi->gpios->ndescs > 32)
+		return dev_err_probe(dev, -EINVAL,
+				     "Number of '%s' gpios limited to 32\n",
+				     labels_property);
+
+	/* Set default value for the kctrl_max. Can be changed later */
+	multi->kctrl_max = (1 << multi->gpios->ndescs) - 1;
+
+	multi->mode = AUDIO_GPIO_MODE_NONE;
+	if (of_property_present(np, points_property)) {
+		ret = audio_gpio_amp_parse_points(dev, multi, points_property);
+		if (ret < 0)
+			return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
+					     points_property);
+		multi->mode = AUDIO_GPIO_MODE_POINTS;
+
+	} else if (of_property_present(np, range_property)) {
+		ret = audio_gpio_amp_parse_range(dev, multi, range_property);
+		if (ret < 0)
+			return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
+					     range_property);
+		multi->mode = AUDIO_GPIO_MODE_RANGE;
+
+	} else if (of_property_present(np, labels_property)) {
+		ret = audio_gpio_amp_parse_labels(dev, multi, labels_property);
+		if (ret < 0)
+			return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
+					     labels_property);
+
+		multi->mode = AUDIO_GPIO_MODE_LABELS;
+	}
+
+	return 0;
+}
+
+static int audio_gpio_amp_parse_single_gpio(struct device *dev,
+					    struct audio_gpio_single *single,
+					    const char *gpio_property)
+{
+	/* Start with the inactive value */
+	single->is_inverted = false;
+	single->kctrl_val = 0;
+	single->gpio = devm_gpiod_get_optional(dev, gpio_property, GPIOD_OUT_LOW);
+	if (IS_ERR(single->gpio))
+		return dev_err_probe(dev, PTR_ERR(single->gpio),
+				     "Failed to get '%s' gpio\n",
+				     gpio_property);
+	return 0;
+}
+
+static int audio_gpio_amp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct audio_gpio_amp *gpio_amp;
+	int ret;
+
+	gpio_amp = devm_kzalloc(dev, sizeof(*gpio_amp), GFP_KERNEL);
+	if (!gpio_amp)
+		return -ENOMEM;
+
+	ret = audio_gpio_amp_parse_single_gpio(dev, &gpio_amp->mute, "mute");
+	if (ret)
+		return ret;
+
+	ret = audio_gpio_amp_parse_single_gpio(dev, &gpio_amp->bypass, "bypass");
+	if (ret)
+		return ret;
+
+	ret = audio_gpio_amp_parse_multi_gpio(dev, &gpio_amp->gain, "gain",
+					      "gain-range", "gain-points", "gain-labels");
+	if (ret)
+		return ret;
+
+	/* Set controls name */
+	gpio_amp->gain.control_name = "Volume";
+	gpio_amp->mute.control_name = "Switch";
+	gpio_amp->bypass.control_name = "Bypass Switch";
+
+	if (gpio_amp->gain.mode == AUDIO_GPIO_MODE_LABELS) {
+		/*
+		 * The gain widget control will use enumerated values.
+		 *
+		 * Having just "Voltage" and "Switch" widget names with
+		 * enumerated values and boolean value can confuse ALSA in terms
+		 * of possible values (strings).
+		 *
+		 * Make things clear and avoid the just "Switch" name in that
+		 * case.
+		 */
+		gpio_amp->mute.control_name = "Out Switch";
+	}
+
+	platform_set_drvdata(pdev, gpio_amp);
+
+	return devm_snd_soc_register_component(dev,
+					       &audio_gpio_amp_component_driver,
+					       NULL, 0);
+}
+
+static const struct of_device_id audio_gpio_amp_ids[] = {
+	{ .compatible = "audio-gpio-amp" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, audio_gpio_amp_ids);
+
+static struct platform_driver audio_gpio_amp_driver = {
+	.driver = {
+		.name = "audio-gpio-amp",
+		.of_match_table = of_match_ptr(audio_gpio_amp_ids),
+	},
+	.probe = audio_gpio_amp_probe,
+};
+module_platform_driver(audio_gpio_amp_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("ASoC GPIOs controlled amplifier driver");
+MODULE_LICENSE("GPL");
-- 
2.53.0


^ permalink raw reply related

* [PATCH 4/4] MAINTAINERS: Add the ASoC gpio amplifier entry
From: Herve Codina @ 2026-03-30 10:16 UTC (permalink / raw)
  To: Herve Codina, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Saravana Kannan,
	Jaroslav Kysela, Takashi Iwai
  Cc: linux-sound, devicetree, linux-kernel, Christophe Leroy,
	Thomas Petazzoni
In-Reply-To: <20260330101610.57942-1-herve.codina@bootlin.com>

After contributing the component, add myself as the maintainer for the
ASoC gpio amplifier component.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 55af015174a5..2546eb81f233 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24765,6 +24765,13 @@ F:	include/sound/dmaengine_pcm.h
 F:	sound/core/pcm_dmaengine.c
 F:	sound/soc/soc-generic-dmaengine-pcm.c
 
+SOUND - SOC LAYER / AUDIO GPIO AMPLIFIER
+M:	Herve Codina <herve.codina@bootlin.com>
+L:	linux-sound@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/sound/audio-gpio-amp.yaml
+F:	sound/soc/codecs/audio-gpio-amp.c
+
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
 M:	Liam Girdwood <lgirdwood@gmail.com>
 M:	Mark Brown <broonie@kernel.org>
-- 
2.53.0


^ permalink raw reply related

* Re: (subset) [PATCH v8 00/10] pmdomain: samsung: add support for Google GS101
From: Krzysztof Kozlowski @ 2026-03-30 10:17 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Alim Akhtar, Rob Herring, Conor Dooley, Krzysztof Kozlowski,
	Liam Girdwood, Mark Brown, André Draszik, Peter Griffin,
	Tudor Ambarus, Juan Yescas, Will McVicker, kernel-team,
	linux-arm-kernel, linux-samsung-soc, devicetree, linux-kernel,
	linux-pm, Marek Szyprowski
In-Reply-To: <CAPDyKFrK3NLwaii-9FEmyaTzUAuVkMkLL3rWBQwQvT-M+PzEHA@mail.gmail.com>

On 30/03/2026 12:13, Ulf Hansson wrote:
> On Mon, 30 Mar 2026 at 11:54, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>
>> On 23/03/2026 12:13, Ulf Hansson wrote:
>>> Hi Krzysztof,
>>>
>>> On Sat, 21 Mar 2026 at 14:18, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>>>
>>>>
>>>> On Wed, 18 Mar 2026 15:27:45 +0000, André Draszik wrote:
>>>>> This series adds support for the power domains on Google GS101.
>>>>>
>>>>> There are a few differences compared to SoCs already supported by this
>>>>> driver:
>>>>> * register access does not work via plain ioremap() / readl() /
>>>>>   writel().
>>>>>   Instead, the regmap created by the PMU driver must be used (which
>>>>>   uses Arm SMCC calls under the hood).
>>>>> * DTZPC: a call needs to be made before and after power domain off/on,
>>>>>   to inform the EL3 firmware of the request.
>>>>> * power domains can and are fed by a regulator rail and therefore
>>>>>   regulator control needed be implemented.
>>>>>
>>>>> [...]
>>>>
>>>> Applied, thanks!
>>>>
>>>> [01/10] dt-bindings: soc: google: add google,gs101-dtzpc
>>>>         https://git.kernel.org/krzk/linux/c/10084aeadadfab72648f6ed1cc78f7cd87b861ba
>>>> [03/10] dt-bindings: soc: samsung: exynos-pmu: move gs101-pmu into separate binding
>>>>         https://git.kernel.org/krzk/linux/c/3ec3c42b426fe5e2b48ff19c551dec50bc78788c
>>>> [04/10] dt-bindings: soc: google: gs101-pmu: allow power domains as children
>>>>         https://git.kernel.org/krzk/linux/c/c8229a5160eea145b796f54317d6e659cec9b080
>>>>
>>>> Best regards,
>>>
>>> Usually I pick up the power-domain related changes for the DT bindings
>>> and host them via an immutable branch called "dt". If needed, SOC
>>> maintainers can pull it to apply/test the corresponding DTS changes.
>>>
>>> That said, I am open to whatever you think is best here. Perhaps it's
>>> easier if you can drop the DT patches and provide your acks instead or
>>> if you can share them via an immutable branch for me to pull?
>>
>>
>> I did not pick up any pmdomain binding patches. I picked up only soc and
>> according to cover letter there are no dependencies between anything here.
> 
> As I understand it, they are all related and some even depend on each

I raised exactly that questions but no answers.

> other. I think keeping all four DT patches together makes sense.

Why? What is the dependency?

> 
> Although, as I said, if you think it's best to funnel them through
> your tree, please do and then share them via an immutable branch, so I
> can apply the pmdomain driver changes.

soc must go via my tree, but there is no reason to take the pmdomain
binding patch. So I did not take.

But anyway, I just noticed that I dropped everything: this introduces
new warnings which were nowhere addressed or explained. So regardless
how this should go, please do not apply anything - it's broken and
author is silent.


Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH v5 6/9] arm64: dts: amlogic: t7: khadas-vim4: Add power regulators
From: Ronald Claveau @ 2026-03-30 10:18 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-arm-kernel, linux-amlogic, devicetree, linux-kernel,
	linux-mmc, linux-wireless, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Ulf Hansson, Johannes Berg, van Spriel
In-Reply-To: <416d42a6-8d99-421c-91aa-e705f23576e2@linaro.org>

On 3/30/26 9:55 AM, Neil Armstrong wrote:
> On 3/26/26 10:59, Ronald Claveau wrote:
>> Add voltage regulator nodes describing the VIM4 power tree,
>> required by peripheral nodes such as the SD card controller.
>>
>> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
>> ---
>>   .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts  | 90 ++++++++++++
>> ++++++++++
>>   1 file changed, 90 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-
>> vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
>> index fffdab96b12eb..2450084d37642 100644
>> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
>> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
>> @@ -6,6 +6,8 @@
>>   /dts-v1/;
>>     #include "amlogic-t7.dtsi"
>> +#include <dt-bindings/gpio/amlogic,t7-periphs-pinctrl.h>
>> +#include <dt-bindings/gpio/gpio.h>
>>     / {
>>       model = "Khadas vim4";
>> @@ -45,6 +47,94 @@ xtal: xtal-clk {
>>           #clock-cells = <0>;
>>       };
>>   +    dc_in: regulator-dc-in {
>> +        compatible = "regulator-fixed";
>> +        regulator-name = "DC_IN";
>> +        regulator-min-microvolt = <5000000>;
>> +        regulator-max-microvolt = <5000000>;
>> +        regulator-always-on;
>> +    };
>> +
>> +    sd_3v3: regulator-sdcard-3v3 {
>> +        compatible = "regulator-fixed";
>> +        regulator-name = "SD_3V3";
>> +        regulator-min-microvolt = <3300000>;
>> +        regulator-max-microvolt = <3300000>;
>> +        vin-supply = <&vddao_3v3>;
>> +        gpio = <&gpio GPIOD_11 GPIO_ACTIVE_LOW>;
>> +        regulator-boot-on;
> 
>> +        enable-active-low;
> 
> This properly is invalid, please send follow up patch removing this,
> 
> Thanks,
> Neil
> 
> <snip>

Sure. I am on it.

Thanks,
-- 
Best regards,
Ronald

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: arm: qcom: Add monaco-evk-ac-sku support
From: Umang Chheda @ 2026-03-30 10:21 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Richard Cochran, linux-arm-msm, devicetree,
	linux-kernel
In-Reply-To: <c7dcab44-68ad-48b7-9ad2-8e2b15951fa7@kernel.org>



On 3/30/2026 3:17 PM, Krzysztof Kozlowski wrote:
> On 30/03/2026 11:36, Umang Chheda wrote:
>> Hello Krzysztof,
>>
>> On 3/30/2026 12:24 PM, Krzysztof Kozlowski wrote:
>>> On 30/03/2026 08:50, Umang Chheda wrote:
>>>> Hello Krzysztof,
>>>>
>>>> On 3/29/2026 3:22 PM, Krzysztof Kozlowski wrote:
>>>>> On Sat, Mar 28, 2026 at 05:11:17PM +0530, Umang Chheda wrote:
>>>>>> Introduce new bindings for the monaco-evk-ac-sku,
>>>>>> an IoT board based on the QCS8300-AC variant SoC.
>>>>> Please wrap commit message according to Linux coding style / submission
>>>>> process (neither too early nor over the limit):
>>>>> https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597
>>>>
>>>>
>>>> Ack
>>>>
>>>>>
>>>>>> Signed-off-by: Umang Chheda <umang.chheda@oss.qualcomm.com>
>>>>>> ---
>>>>>>  Documentation/devicetree/bindings/arm/qcom.yaml | 1 +
>>>>>>  1 file changed, 1 insertion(+)
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
>>>>>> index ca880c105f3b..07053cc2ac1c 100644
>>>>>> --- a/Documentation/devicetree/bindings/arm/qcom.yaml
>>>>>> +++ b/Documentation/devicetree/bindings/arm/qcom.yaml
>>>>>> @@ -918,6 +918,7 @@ properties:
>>>>>>            - enum:
>>>>>>                - arduino,monza
>>>>>>                - qcom,monaco-evk
>>>>>> +              - qcom,monaco-evk-ac-sku
>>>>> Why adding name 'sku' to the compatible? What's the meaning here?
>>>>
>>>>
>>>> Monaco SoC has 2 variants  - monaco-aa and monaco-ac -- "monaco-evk" board uses monaco-aa variant of SoC and this new
>>>
>>> so ac? or ac-sku? Decide.
>>>
>>>> introduced board uses the monaco-ac variant SoC. Hence added the compatible as "monaco-evk-ac-sku" to differentiate it from
>>>> monaco-evk board.
>>>
>>> Wrap your emails.
>>
>> Ack
>>>
>>> "ac" differentiates. Why do you need to say that a variant is a
>>> "-variant"?
>>>
>>
>> The intent for using "-sku" here was to match the existing upstream
>> practice where boards that are otherwise identical but differ in H/W
>> configuration (SoC variant, storage etc) are represented as separate SKUs.
>>
>> For Example:
>>   - sc7180-trogdor-*-sku.dtsi
>>   - sc7280-herobrine-*-sku.dtsi
>>   - mt8183-kukui-jacuzzi-*-sku.dts
> 
> We talk about compatible, why any of DTS names matter? You don't
> understand the meaning of sku. It makes no sense without the number/ID.
> It's like you called it "-revision"...

Thanks for the explanation - I get it now!

I agree that encoding this as "qcom,monaco-evk-ac" is sufficient for
the compatible, and that "-sku" does not add additional compatibility
information.

I will update the binding to drop "-sku" from the compatible.

Thanks for the review.

> 
> Best regards,
> Krzysztof

Thanks,
Umang


^ permalink raw reply

* [PATCH] arm64: dts: amlogic: t7: khadas-vim4: Remove invalid property
From: Ronald Claveau @ 2026-03-30 10:21 UTC (permalink / raw)
  To: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-kernel, linux-amlogic, devicetree, linux-kernel,
	kernel test robot, Ronald Claveau

Fix introduced invalid property for Khadas VIM4 sdcard regulator.

arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dtb: regulator-sdcard-3v3 (regulator-fixed): Unevaluated properties are not allowed ('enable-active-low' was unexpected)

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603290828.5gt393t6-lkp@intel.com/
Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 11bfbc99191b6..003b3bcdaf2bc 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -65,7 +65,6 @@ sd_3v3: regulator-sdcard-3v3 {
 		vin-supply = <&vddao_3v3>;
 		gpio = <&gpio GPIOD_11 GPIO_ACTIVE_LOW>;
 		regulator-boot-on;
-		enable-active-low;
 		regulator-always-on;
 	};
 

---
base-commit: 3b058d1aeeeff27a7289529c4944291613b364e9
change-id: 20260330-fix-invalid-property-bbe54d933f71

Best regards,
-- 
Ronald Claveau <linux-kernel-dev@aliel.fr>


^ permalink raw reply related

* Re: [PATCH v2 0/7] Add vibrator, IR transmitter and USB-C handling in xiaomi-ginkgo
From: Biswapriyo Nath @ 2026-03-30 10:22 UTC (permalink / raw)
  To: Biswapriyo Nath
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Lee Jones, Pavel Machek, Sean Young,
	Michael Turquette, Stephen Boyd, Martin Botka, linux-arm-msm,
	devicetree, linux-kernel, linux-leds, linux-clk,
	~postmarketos/upstreaming, phone-devel, stable, kernel test robot,
	Konrad Dybcio, Dmitry Baryshkov, Krzysztof Kozlowski
In-Reply-To: <20260329-ginkgo-add-usb-ir-vib-v2-0-870e0745e55e@gmail.com>

On Sun, 29 Mar 2026 04:47:55 +0000 Biswapriyo Nath <nathbappai@gmail.com> wrote:

> This patch series add support for various components in Xiaomi Redmi
> Note 8.
> 

v3 of this patch series was sent here[1].

[1]: https://lore.kernel.org/linux-arm-msm/20260330-ginkgo-add-usb-ir-vib-v3-0-c4b778b0d7f8@gmail.com/


^ permalink raw reply

* [PATCH 0/2] Add support for Infineon Digital eFuse XDP720
From: ASHISH YADAV @ 2026-03-30 10:23 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, Ashish Yadav

From: Ashish Yadav <ashish.yadav@infineon.com>

Hi,

These patches add support for Infineon Digital eFuse XDP720.
XDP720 provides accurate system telemetry (V, I, P, T) and
reports analog current at the IMON pin for post-processing.

The Current and Power measurement depends on the RIMON and GIMON values.
Please look into data sheet sections 5.4.2 and 5.4.4 for more details:
https://www.infineon.com/assets/row/public/documents/24/49/infineon-xdp720-001-datasheet-en.pdf

With Best Regards,
 Ashish Yadav


Ashish Yadav (2):
  dt-bindings: hwmon/pmbus: Add Infineon XDP720
  hwmon:(pmbus/xdp720) Add support for efuse xdp720

 .../bindings/hwmon/pmbus/infineon,xdp720.yaml |  52 ++++++++
 drivers/hwmon/pmbus/Kconfig                   |   9 ++
 drivers/hwmon/pmbus/Makefile                  |   1 +
 drivers/hwmon/pmbus/xdp720.c                  | 122 ++++++++++++++++++
 4 files changed, 184 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/pmbus/infineon,xdp720.yaml
 create mode 100644 drivers/hwmon/pmbus/xdp720.c

-- 
2.39.5


^ permalink raw reply

* [PATCH 1/2] dt-bindings: hwmon/pmbus: Add Infineon XDP720
From: ASHISH YADAV @ 2026-03-30 10:23 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, Ashish Yadav
In-Reply-To: <20260330102345.37065-1-Ashish.Yadav@infineon.com>

From: Ashish Yadav <ashish.yadav@infineon.com>

Add documentation for the device tree binding of the XDP720 eFuse.

Signed-off-by: Ashish Yadav <ashish.yadav@infineon.com>
---

This patch introduces a YAML schema describing the required and optional
properties for the XDP720 eFuse device node. It includes details on the
compatible string, register mapping, and rimon-micro-ohms(RIMON).

The RIMON resistance is installed between the Imon pin and the ground
reference.
---
 .../bindings/hwmon/pmbus/infineon,xdp720.yaml | 52 +++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/pmbus/infineon,xdp720.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/infineon,xdp720.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,xdp720.yaml
new file mode 100644
index 000000000000..09249a326eee
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/infineon,xdp720.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/hwmon/pmbus/infineon,xdp720.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Infineon XDP720 Digital eFuse Controller
+
+maintainers:
+  - Ashish Yadav <ashish.yadav@infineon.com>
+
+description: |
+  The XDP720 is an eFuse with integrated  current sensor and digital
+  controller. It provides accurate system telemetry (V, I, P, T) and
+  reports analog current at the IMON pin for post-processing.
+
+   Datasheet:
+     https://www.infineon.com/assets/row/public/documents/24/49/infineon-xdp720-001-datasheet-en.pdf
+
+properties:
+  compatible:
+    enum:
+      - infineon,xdp720
+
+  reg:
+    maxItems: 1
+
+  infineon,rimon-micro-ohms:
+    description: |
+      The value of the RIMON resistor, in micro‑ohms, required to enable
+      the system’s over‑current protection.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        hwmon@11 {
+            compatible = "infineon,xdp720";
+            reg = <0x11>;
+            infineon,rimon-micro-ohms = <1098000000>;  /* 1.098k ohm */
+        };
+    };
-- 
2.39.5


^ permalink raw reply related

* [PATCH 2/2] hwmon:(pmbus/xdp720) Add support for efuse xdp720
From: ASHISH YADAV @ 2026-03-30 10:23 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-hwmon, devicetree, linux-kernel, Ashish Yadav
In-Reply-To: <20260330102345.37065-1-Ashish.Yadav@infineon.com>

From: Ashish Yadav <ashish.yadav@infineon.com>

Add the pmbus driver for Infineon XDP720 Digital eFuse Controller.

Signed-off-by: Ashish Yadav <ashish.yadav@infineon.com>
---
XDP720 Digital eFuse Controller provides accurate system telemetry
(V, I, P, T) and reports analog current at the IMON pin for post-processing.

The Current and Power measurement depends on the RIMON and GIMON values.
Please look into data sheet sections 5.4.2 and 5.4.4 for more details:
https://www.infineon.com/assets/row/public/documents/24/49/infineon-xdp720-001-datasheet-en.pdf

The GIMON (microA/A) depends on the 10th bit of TELEMETRY_AVG PMBUS Register.
The value of RIMON (kohm) can be provided by the user through device tree using
infineon,rimon-micro-ohms  property.
---
 drivers/hwmon/pmbus/Kconfig  |   9 +++
 drivers/hwmon/pmbus/Makefile |   1 +
 drivers/hwmon/pmbus/xdp720.c | 122 +++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 drivers/hwmon/pmbus/xdp720.c

diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index fc1273abe357..c8e53852d0c3 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -702,6 +702,15 @@ config SENSORS_XDP710
 	  This driver can also be built as a module. If so, the module will
 	  be called xdp710.
 
+config SENSORS_XDP720
+        tristate "Infineon XDP720 family"
+        help
+          If you say yes here you get hardware monitoring support for Infineon
+          XDP720.
+
+          This driver can also be built as a module. If so, the module will
+          be called xdp720.
+
 config SENSORS_XDPE152
 	tristate "Infineon XDPE152 family"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index d6c86924f887..bb0a7526d5b3 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_SENSORS_TPS546D24)	+= tps546d24.o
 obj-$(CONFIG_SENSORS_UCD9000)	+= ucd9000.o
 obj-$(CONFIG_SENSORS_UCD9200)	+= ucd9200.o
 obj-$(CONFIG_SENSORS_XDP710)	+= xdp710.o
+obj-$(CONFIG_SENSORS_XDP720)    += xdp720.o
 obj-$(CONFIG_SENSORS_XDPE122)	+= xdpe12284.o
 obj-$(CONFIG_SENSORS_XDPE152)	+= xdpe152c4.o
 obj-$(CONFIG_SENSORS_ZL6100)	+= zl6100.o
diff --git a/drivers/hwmon/pmbus/xdp720.c b/drivers/hwmon/pmbus/xdp720.c
new file mode 100644
index 000000000000..862de828198d
--- /dev/null
+++ b/drivers/hwmon/pmbus/xdp720.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for Infineon XDP720 Digital eFuse Controller
+ *
+ * Copyright (c) 2026 Infineon Technologies. All rights reserved.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/bitops.h>
+#include "pmbus.h"
+
+/*
+ * The IMON resistor required to generate the system overcurrent protection.
+ * Arbitrary default Rimon value: 2k Ohm
+ */
+#define XDP720_DEFAULT_RIMON 2000000000 /* 2k ohm */
+#define XDP720_TELEMETRY_AVG 0xE9
+
+static struct pmbus_driver_info xdp720_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = direct,
+	.format[PSC_VOLTAGE_OUT] = direct,
+	.format[PSC_CURRENT_OUT] = direct,
+	.format[PSC_POWER] = direct,
+	.format[PSC_TEMPERATURE] = direct,
+
+	.m[PSC_VOLTAGE_IN] = 4653,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = -2,
+	.m[PSC_VOLTAGE_OUT] = 4653,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = -2,
+	/*
+	 * Current and Power measurement depends on the RIMON (kOhm) and
+	 * GIMON(microA/A) values.
+	 */
+	.m[PSC_CURRENT_OUT] = 24668,
+	.b[PSC_CURRENT_OUT] = 0,
+	.R[PSC_CURRENT_OUT] = -4,
+	.m[PSC_POWER] = 4486,
+	.b[PSC_POWER] = 0,
+	.R[PSC_POWER] = -1,
+	.m[PSC_TEMPERATURE] = 54,
+	.b[PSC_TEMPERATURE] = 22521,
+	.R[PSC_TEMPERATURE] = -1,
+
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_PIN |
+		   PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_INPUT |
+		   PMBUS_HAVE_STATUS_TEMP,
+};
+
+static int xdp720_probe(struct i2c_client *client)
+{
+	struct pmbus_driver_info *info;
+	int ret;
+	u32 rimon;
+	int gimon;
+
+	info = devm_kmemdup(&client->dev, &xdp720_info, sizeof(*info),
+			    GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	ret = i2c_smbus_read_word_data(client, XDP720_TELEMETRY_AVG);
+	if (ret < 0) {
+		dev_err(&client->dev, "Can't get TELEMETRY_AVG\n");
+		return ret;
+	}
+
+	ret >>= 10; /* 10th bit of TELEMETRY_AVG REG for GIMON Value */
+	ret &= GENMASK(0, 0);
+	if (ret == 1)
+		gimon = 18200; /* output gain 18.2 microA/A */
+	else
+		gimon = 9100; /* output gain 9.1 microA/A */
+
+	if (of_property_read_u32(client->dev.of_node,
+				 "infineon,rimon-micro-ohms", &rimon))
+		rimon = XDP720_DEFAULT_RIMON; /* Default if not set via DT */
+	if (rimon == 0)
+		return -EINVAL;
+
+	/* Adapt the current and power scale for each instance */
+	info->m[PSC_CURRENT_OUT] = DIV_ROUND_CLOSEST_ULL((u64)
+		info->m[PSC_CURRENT_OUT] * rimon * gimon, 1000000000000);
+	info->m[PSC_POWER] = DIV_ROUND_CLOSEST_ULL((u64)
+		info->m[PSC_POWER] * rimon * gimon, 1000000000000);
+
+	return pmbus_do_probe(client, info);
+}
+
+static const struct of_device_id xdp720_of_match[] = {
+	{ .compatible = "infineon,xdp720" },
+	{}
+};
+
+static const struct i2c_device_id xdp720_id[] = {
+	{ "xdp720" },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, xdp720_id);
+
+static struct i2c_driver xdp720_driver = {
+	.driver = {
+		   .name = "xdp720",
+		   .of_match_table = xdp720_of_match,
+	},
+	.probe = xdp720_probe,
+	.id_table = xdp720_id,
+};
+
+module_i2c_driver(xdp720_driver);
+
+MODULE_AUTHOR("Ashish Yadav <ashish.yadav@infineon.com>");
+MODULE_DESCRIPTION("PMBus driver for Infineon Digital eFuse Controller");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("PMBUS");
-- 
2.39.5


^ permalink raw reply related

* Re: [PATCH] dt-bindings: display: bridge: ldb: Require reg property only for i.MX6SX/8MP LDBs
From: Marco Felsch @ 2026-03-30 10:28 UTC (permalink / raw)
  To: Liu Ying
  Cc: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Marek Vasut, Laurentiu Palcu,
	dri-devel, devicetree, linux-kernel
In-Reply-To: <aabe88e5-70f9-4ea1-b750-e425970a2761@nxp.com>

On 26-03-30, Liu Ying wrote:
> On Sun, Mar 29, 2026 at 07:42:23PM +0200, Marco Felsch wrote:
> > Hi Liu,
> 
> Hi Marco,
> 
> > 
> > sorry for not writting back earlier, the last weeks were quite busy.
> > 
> > On 26-03-29, Liu Ying wrote:
> >> LDB's parent device could be a syscon which doesn't allow a reg property
> >> to be present in it's child devices, e.g., NXP i.MX93 Media blk-ctrl
> >> has a child device NXP i.MX93 Parallel Display Format Configuration(PDFC)
> >> without a reg property(LDB is also a child device of the Media blk-ctrl).
> >> To make the LDB schema be able to describe LDBs without the reg property
> >> like i.MX93 LDB, require the reg property only for i.MX6SX/8MP LDBs.
> > 
> > NACK, we want to describe the HW and from HW PoV the LDB is and was
> > always part of a syscon. This is the case for all SoCs i.MX6SX/8MP/93.
> 
> The reality is that i.MX6SX and i.MX8MP LDB DT nodes are already in-tree.

What do you mean by 'already in-tee'?

> People may take them as ABI(not only for Linux, but also for other
> potential projects which use the LDB schema and/or the DT nodes).

Not sure about this. The DT sould be backward compatible, meaning an old
DT shouldn't break new users e.g. old DT with 'reg' property present
shouldn't break new u-boot/barebox/linux/... drivers. But a new DT could
fix/change the behavior for new u-boot/barebox/linux/... drivers.

So no, I don't see a problem here.

> >> Fixes: 8aa2f0ac08d3 ("dt-bindings: display: bridge: ldb: Add check for reg and reg-names")
> > 
> > Therefore I would just revert this patch completely.
> 
> IMHO, it doesn't make too much difference between my patch and reverting
> this offending patch, because of the ABI, i.e., the reg properties in
> i.MX6SX and i.MX8MP LDB DT nodes are supposed to be stable.

Please see above. If that would be the case, your DT must be rock-solid
bug-free from day one, which is highly unlikely.

> I feel that what you are asking for is even more than simply reverting
> this offending patch, that is to say, completely disallowing the reg and
> reg-names properties for LDBs across all SoCs.  But again, that would
> break the ABI.

Please see above. IMHO it's more confusing if the same "IP" requires the
'reg' for i.MX6SX/8MP but doesn't require it for the i.MX93. Therefore I
would like to keep it consistent.

Regards,
  Marco

> 
> > 
> > Regards,
> >   Marco
> > 
> >> Signed-off-by: Liu Ying <victor.liu@nxp.com>
> >> ---
> >>  .../bindings/display/bridge/fsl,ldb.yaml           | 23 ++++++++++++++++------
> >>  1 file changed, 17 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml
> >> index 7f380879fffd..5f6dc2b11d7b 100644
> >> --- a/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml
> >> +++ b/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml
> >> @@ -28,6 +28,7 @@ properties:
> >>      const: ldb
> >>  
> >>    reg:
> >> +    minItems: 1
> >>      maxItems: 2
> >>  
> >>    reg-names:
> >> @@ -68,7 +69,6 @@ required:
> >>    - compatible
> >>    - clocks
> >>    - ports
> >> -  - reg
> >>  
> >>  allOf:
> >>    - if:
> >> @@ -83,12 +83,23 @@ allOf:
> >>          ports:
> >>            properties:
> >>              port@2: false
> >> +
> >>    - if:
> >> -      not:
> >> -        properties:
> >> -          compatible:
> >> -            contains:
> >> -              const: fsl,imx6sx-ldb
> >> +      properties:
> >> +        compatible:
> >> +          contains:
> >> +            enum:
> >> +              - fsl,imx6sx-ldb
> >> +              - fsl,imx8mp-ldb
> >> +    then:
> >> +      required:
> >> +        - reg
> >> +
> >> +  - if:
> >> +      properties:
> >> +        compatible:
> >> +          contains:
> >> +            const: fsl,imx8mp-ldb
> >>      then:
> >>        required:
> >>          - reg-names
> >>
> >> ---
> >> base-commit: 3b058d1aeeeff27a7289529c4944291613b364e9
> >> change-id: 20260329-fsl_ldb_schema_fix-4fe01c42bff3
> >>
> >> Best regards,
> >> -- 
> >> Liu Ying <victor.liu@nxp.com>
> >>
> >>
> > 
> 
> -- 
> Regards,
> Liu Ying
> 

-- 
#gernperDu 
#CallMeByMyFirstName

Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | https://www.pengutronix.de/ |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-9    |

^ permalink raw reply

* [PATCH 6/7] dts: riscv: update cache compatible strings to LLC
From: Hui Min Mina Chou @ 2026-03-30 10:27 UTC (permalink / raw)
  To: pjw, palmer, aou, alex, geert+renesas, prabhakar.mahadev-lad.rj,
	magnus.damm, ben717, robh, krzk+dt, conor+dt, jonathan.cameron,
	devicetree, linux-riscv, linux-kernel, linux-renesas-soc
  Cc: tim609, alex749, az70021, Hui Min Mina Chou
In-Reply-To: <20260330102724.1012470-1-minachou@andestech.com>

Update the cache driver compatible strings from ax45mp-cache to llcache
for both Qilai and RZ/Five platforms.
This follows the Andes cache driver refactoring to use more generic
Last Level Cache (LLC) naming.

Signed-off-by: Hui Min Mina Chou <minachou@andestech.com>
---
 arch/riscv/boot/dts/andes/qilai.dtsi        | 4 ++--
 arch/riscv/boot/dts/renesas/r9a07g043f.dtsi | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/boot/dts/andes/qilai.dtsi b/arch/riscv/boot/dts/andes/qilai.dtsi
index de3de32f8c39..a7436cbf6f69 100644
--- a/arch/riscv/boot/dts/andes/qilai.dtsi
+++ b/arch/riscv/boot/dts/andes/qilai.dtsi
@@ -137,8 +137,8 @@ plmt: timer@100000 {
 		};
 
 		l2_cache: cache-controller@200000 {
-			compatible = "andestech,qilai-ax45mp-cache",
-				     "andestech,ax45mp-cache", "cache";
+			compatible = "andestech,qilai-llcache",
+				     "andestech,llcache", "cache";
 			reg = <0x0 0x00200000 0x0 0x100000>;
 			interrupts = <16 IRQ_TYPE_LEVEL_HIGH>;
 			cache-line-size = <64>;
diff --git a/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi b/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
index 571de3cafa82..83a5d4d41f8e 100644
--- a/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
+++ b/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
@@ -144,7 +144,7 @@ plic: interrupt-controller@12c00000 {
 	};
 
 	l2cache: cache-controller@13400000 {
-		compatible = "renesas,r9a07g043f-ax45mp-cache", "andestech,ax45mp-cache",
+		compatible = "renesas,r9a07g043f-llcache", "andestech,llcache",
 			     "cache";
 		reg = <0x0 0x13400000 0x0 0x100000>;
 		interrupts = <SOC_PERIPHERAL_IRQ(476) IRQ_TYPE_LEVEL_HIGH>;
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v4 3/4] thermal/qcom/lmh: support SDM670 and its CPU clusters
From: Konrad Dybcio @ 2026-03-30 10:32 UTC (permalink / raw)
  To: Dmitry Baryshkov, Richard Acayan
  Cc: Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Amit Kucheria,
	Thara Gopinath, Bjorn Andersson, Konrad Dybcio, linux-arm-msm,
	linux-pm, devicetree
In-Reply-To: <a3rrkgvkc4zxcq5oqvws23lyjy6dinlmfgp34wzguvdxdxig5f@25atyxc7zabm>

On 3/29/26 12:44 PM, Dmitry Baryshkov wrote:
> On Fri, Mar 27, 2026 at 09:40:40PM -0400, Richard Acayan wrote:
>> The LMh driver was made for Qualcomm SoCs with clusters of 4 CPUs, but
>> some SoCs divide the CPUs into different sizes of clusters. In SDM670,
>> the first 6 CPUs are in the little cluster and the next 2 are in the big
>> cluster. Define the clusters in the match data and define the different
>> cluster configuration for SDM670.
>>
>> Currently, this only supports 8 CPUs and tolerates linking to any CPU in
>> the cluster.
>>
>> Signed-off-by: Richard Acayan <mailingradian@gmail.com>
>> ---
>>  drivers/thermal/qcom/lmh.c | 69 +++++++++++++++++++++++++++++++-------
>>  1 file changed, 56 insertions(+), 13 deletions(-)
>>
>> +static const struct lmh_soc_data sdm670_lmh_data = {
>> +	.enable_algos = true,
>> +	.node_ids = {
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +	},
>> +};
>> +
>> +static const struct lmh_soc_data sdm845_lmh_data = {
>> +	.enable_algos = true,
>> +	.node_ids = {
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +	},
>> +};
> 
> These tables made me wonder, can we determine this information from the
> DT? For example, by reading the qcom,freq-domain property. But...
> 
>> +
>> +static const struct lmh_soc_data sm8150_lmh_data = {
>> +	.enable_algos = false,
>> +	.node_ids = {
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER0_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +		LMH_CLUSTER1_NODE_ID,
>> +	},
>> +};
> 
> ... this might be problematic, unless this entry is broken. On SM8150 we
> have three freq domains, but up to now we were programming two clustern
> nodes. Of course it is possible to define that node_id is 0 for freq
> domain 0 and 1 for domains 1 and 2.

The third cluster situation on 8150 is not super good - we e.g. only have
a single LMH irq that's shared between the big and prime cores. That
was fixed with later SoCs (which is why it's not wired up in the DT today)

Funnily enough the bigger 8180 didn't have that problem because it only had
2 freq domains

Konrad

^ permalink raw reply

* Re: [PATCH v2 6/7] dt-bindings: PCI: intel,lgm-pcie: Make atu resource mandatory
From: Rob Herring (Arm) @ 2026-03-30 10:35 UTC (permalink / raw)
  To: Florian Eckert
  Cc: Johan Hovold, Krzysztof Kozlowski, devicetree, Lorenzo Pieralisi,
	linux-kernel, Ajay Agarwal, Rahul Tanwar, linux-pci, Sajid Dalvi,
	Eckert.Florian, ms, Manivannan Sadhasivam,
	Krzysztof Wilczyński, Conor Dooley, Bjorn Helgaas
In-Reply-To: <20260330-pcie-intel-gw-v2-6-8bd07367a298@dev.tdt.de>


On Mon, 30 Mar 2026 11:07:16 +0200, Florian Eckert wrote:
> The ATU information is already set in the dwc core if it is specified in
> the DTS. The driver uses its own value here [1]. This information is
> hardware specific and should therefore be maintained in the DTS rather
> than in the source.
> 
> Backwards compatibility is not an issue here [5], as the driver is
> exclusively used by Maxlinear.
> 
> Old DTS entry for PCIe:
> 
> reg = <0xd1000000 0x1000>,
>       <0xd3000000 0x20000>,
>       <0xd0c41000.0x1000>;
> reg-names = "dbi", "config", "app";
> 
> New DTS entry for PCIe:
> 
> reg = <0xd1000000 0x1000>,
>       <0xd10c0000 0x1000>,
>       <0xd3000000 0x20000>,
>      <0xd0c41000.0x1000>;
> reg-names = "dbi", "atu", "config", "app";
> 
> [1] https://elixir.bootlin.com/linux/v6.19.10/source/drivers/pci/controller/dwc/pcie-intel-gw.c#L301
> [2] https://lore.kernel.org/all/BY3PR19MB507667CE7531D863E1E5F8AEBDD82@BY3PR19MB5076.namprd19.prod.outlook.com/
> 
> Signed-off-by: Florian Eckert <fe@dev.tdt.de>
> ---
>  Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Lexical error: Documentation/devicetree/bindings/pci/intel-gw-pcie.example.dts:28.37-43 Unexpected 'config'
Error: Documentation/devicetree/bindings/pci/intel-gw-pcie.example.dts:28.37-43 syntax error
FATAL ERROR: Unable to parse input tree
make[2]: *** [scripts/Makefile.dtbs:140: Documentation/devicetree/bindings/pci/intel-gw-pcie.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1601: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.kernel.org/project/devicetree/patch/20260330-pcie-intel-gw-v2-6-8bd07367a298@dev.tdt.de

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply

* Re: [PATCH v3 04/15] firmware: qcom: Add a PAS TEE service
From: Harshal Dev @ 2026-03-30 10:36 UTC (permalink / raw)
  To: Sumit Garg, linux-arm-msm, devicetree, dri-devel, freedreno,
	linux-media, netdev, linux-wireless, ath12k, linux-remoteproc
  Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
	sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
	airlied, simona, vikash.garodia, dikshita.agarwal, bod, mchehab,
	elder, andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
	mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
	jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
	amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
	linux-kernel, Sumit Garg
In-Reply-To: <20260327131043.627120-5-sumit.garg@kernel.org>



On 3/27/2026 6:40 PM, Sumit Garg wrote:
> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
> 
> Add support for Peripheral Authentication Service (PAS) driver based
> on TEE bus with OP-TEE providing the backend PAS service implementation.
> 
> The TEE PAS service ABI is designed to be extensible with additional API
> as PTA_QCOM_PAS_CAPABILITIES. This allows to accommodate any future
> extensions of the PAS service needed while still maintaining backwards
> compatibility.
> 
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
> ---
>  drivers/firmware/qcom/Kconfig        |  10 +
>  drivers/firmware/qcom/Makefile       |   1 +
>  drivers/firmware/qcom/qcom_pas_tee.c | 478 +++++++++++++++++++++++++++
>  3 files changed, 489 insertions(+)
>  create mode 100644 drivers/firmware/qcom/qcom_pas_tee.c
>
[...]

> diff --git a/drivers/firmware/qcom/qcom_pas_tee.c b/drivers/firmware/qcom/qcom_pas_tee.c
> new file mode 100644
> index 000000000000..d63122c34f04
> --- /dev/null
> +++ b/drivers/firmware/qcom/qcom_pas_tee.c
> @@ -0,0 +1,478 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +#include <linux/firmware/qcom/qcom_pas.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/tee_drv.h>
> +#include <linux/uuid.h>
> +
> +#include "qcom_pas.h"
> +
> +/*
> + * Peripheral Authentication Service (PAS) supported.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + */
> +#define TA_QCOM_PAS_IS_SUPPORTED		1
> +
> +/*
> + * PAS capabilities.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + * [out] params[1].value.a:	PAS capability flags
> + */
> +#define TA_QCOM_PAS_CAPABILITIES		2
> +
> +/*
> + * PAS image initialization.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + * [in]  params[1].memref:	Loadable firmware metadata
> + */
> +#define TA_QCOM_PAS_INIT_IMAGE			3
> +
> +/*
> + * PAS memory setup.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + * [in]  params[0].value.b:	Relocatable firmware size
> + * [in]  params[1].value.a:	32bit LSB relocatable firmware memory address
> + * [in]  params[1].value.b:	32bit MSB relocatable firmware memory address
> + */
> +#define TA_QCOM_PAS_MEM_SETUP			4
> +
> +/*
> + * PAS get resource table.
> + *
> + * [in]     params[0].value.a:	Unique 32bit remote processor identifier
> + * [inout]  params[1].memref:	Resource table config
> + */
> +#define TA_QCOM_PAS_GET_RESOURCE_TABLE		5
> +
> +/*
> + * PAS image authentication and co-processor reset.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + * [in]  params[0].value.b:	Firmware size
> + * [in]  params[1].value.a:	32bit LSB firmware memory address
> + * [in]  params[1].value.b:	32bit MSB firmware memory address
> + * [in]  params[2].memref:	Optional fw memory space shared/lent
> + */
> +#define TA_QCOM_PAS_AUTH_AND_RESET		6
> +
> +/*
> + * PAS co-processor set suspend/resume state.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + * [in]  params[0].value.b:	Co-processor state identifier
> + */
> +#define TA_QCOM_PAS_SET_REMOTE_STATE		7
> +
> +/*
> + * PAS co-processor shutdown.
> + *
> + * [in]  params[0].value.a:	Unique 32bit remote processor identifier
> + */
> +#define TA_QCOM_PAS_SHUTDOWN			8
> +
> +#define TEE_NUM_PARAMS				4
> +
> +/**
> + * struct qcom_pas_tee_private - PAS service private data
> + * @dev:		PAS service device.
> + * @ctx:		TEE context handler.
> + * @session_id:		PAS TA session identifier.

Nit: Column alignment of comment descriptions.

> + */
> +struct qcom_pas_tee_private {
> +	struct device *dev;
> +	struct tee_context *ctx;
> +	u32 session_id;
> +};
> +
> +static bool qcom_pas_tee_supported(struct device *dev, u32 pas_id)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_IS_SUPPORTED,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = pas_id
> +		}
> +	};
> +	int ret;
> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS not supported, pas_id: %d, err: %x\n",
> +			pas_id, inv_arg.ret);

I can see that similar error handling pattern for tee_client_invoke_func() is
being done by other clients. But it seems that this error log doesn't really convey
whether we failed before or after entering OPTEE (or some other TEE) for invoking
the service.

Could be better if we print 'ret' when ret < 0. And print 'inv_arg.ret' when
inv_arg.ret != 0. So for example, if the param marshalling fails, or some other
issue is encountered when processing the params in a different back-end TEE
driver, we could know from the logs.

> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +static int qcom_pas_tee_init_image(struct device *dev, u32 pas_id,
> +				   const void *metadata, size_t size,
> +				   struct qcom_pas_context *ctx)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_INIT_IMAGE,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = pas_id
> +		},
> +		[1] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT,
> +		}
> +	};
> +	struct tee_shm *mdata_shm;
> +	u8 *mdata_buf = NULL;
> +	int ret;
> +
> +	if (!ctx)
> +		return -EINVAL;
> +
> +	mdata_shm = tee_shm_alloc_kernel_buf(data->ctx, size);

Why not move the DEFINE_FREE() above this function so we can use scoped free
here as well for mdata_shm?

struct tee_shm *mdata_shm __free(shm_free) = ...

> +	if (IS_ERR(mdata_shm)) {
> +		dev_err(dev, "mdata_shm allocation failed\n");
> +		return PTR_ERR(mdata_shm);
> +	}
> +
> +	mdata_buf = tee_shm_get_va(mdata_shm, 0);
> +	if (IS_ERR(mdata_buf)) {
> +		dev_err(dev, "mdata_buf get VA failed\n");
> +		tee_shm_free(mdata_shm);
> +		return PTR_ERR(mdata_buf);
> +	}
> +	memcpy(mdata_buf, metadata, size);
> +
> +	param[1].u.memref.shm = mdata_shm;
> +	param[1].u.memref.size = size;
> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS init image failed, pas_id: %d, err: %x\n",

Nit: We can prefix %x with 0x. "err: 0x%x\n."

> +			pas_id, inv_arg.ret);
> +		tee_shm_free(mdata_shm);
> +		return -EINVAL;
> +	}
> +	ctx->ptr = (void *)mdata_shm;
> +
> +	return 0;
> +}
> +
> +static int qcom_pas_tee_mem_setup(struct device *dev, u32 pas_id,
> +				  phys_addr_t addr, phys_addr_t size)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_MEM_SETUP,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = pas_id,
> +			.u.value.b = size,
> +		},
> +		[1] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = lower_32_bits(addr),
> +			.u.value.b = upper_32_bits(addr),
> +		}
> +	};
> +	int ret;
> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS mem setup failed, pas_id: %d, err: %x\n",
> +			pas_id, inv_arg.ret);
> +		return -EINVAL;

I can see that originally in-case of error, qcom_scm_pas_mem_setup() bubbles
up the return value from qcom_scm_call(). Perhaps we should do the same as well,
return ret here instead of hard-coded '-EINVAL' which overrides any useful
return values returned from the back-end TEE driver.
 
> +	}
> +
> +	return 0;
> +}
> +
> +DEFINE_FREE(shm_free, struct tee_shm *, tee_shm_free(_T))
> +
> +static void *qcom_pas_tee_get_rsc_table(struct device *dev,
> +					struct qcom_pas_context *ctx,
> +					void *input_rt, size_t input_rt_size,
> +					size_t *output_rt_size)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_GET_RESOURCE_TABLE,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = ctx->pas_id,
> +		},
> +		[1] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT,
> +			.u.memref.size = input_rt_size,
> +		}
> +	};
> +	void *rt_buf = NULL;
> +	int ret;
> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS get RT failed, pas_id: %d, err: %x\n",
> +			ctx->pas_id, inv_arg.ret);
> +		return ERR_PTR(-EINVAL);

Same comment here, we could return ERR_PTR(ret) instead of overriding to
'-EINVAL'.

> +	}
> +
> +	if (param[1].u.memref.size) {
> +		struct tee_shm *rt_shm __free(shm_free) =
> +			tee_shm_alloc_kernel_buf(data->ctx,
> +						 param[1].u.memref.size);
> +		void *rt_shm_va;
> +
> +		if (IS_ERR(rt_shm)) {
> +			dev_err(dev, "rt_shm allocation failed\n");
> +			return rt_shm;
> +		}
> +
> +		rt_shm_va = tee_shm_get_va(rt_shm, 0);
> +		if (IS_ERR_OR_NULL(rt_shm_va)) {
> +			dev_err(dev, "rt_shm get VA failed\n");
> +			return ERR_PTR(-EINVAL);

Why not just return rt_shm_va? It already encodes the error in the pointer.

> +		}
> +		memcpy(rt_shm_va, input_rt, input_rt_size);
> +
> +		param[1].u.memref.shm = rt_shm;
> +		ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +		if (ret < 0 || inv_arg.ret != 0) {
> +			dev_err(dev, "PAS get RT failed, pas_id: %d, err: %x\n",
> +				ctx->pas_id, inv_arg.ret);
> +			return ERR_PTR(-EINVAL);

Same comment.

> +		}
> +
> +		if (param[1].u.memref.size) {

Is it possible for param[1].u.memref.size to be 0 after a successful tee_client_invoke_func()?

> +			*output_rt_size = param[1].u.memref.size;
> +			rt_buf = kmemdup(rt_shm_va, *output_rt_size, GFP_KERNEL);
> +			if (!rt_buf)
> +				return ERR_PTR(-ENOMEM);
> +		}
> +	}
> +
> +	return rt_buf;
> +}
> +
> +static int __qcom_pas_tee_auth_and_reset(struct device *dev, u32 pas_id,
> +					 phys_addr_t mem_phys, size_t mem_size)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_AUTH_AND_RESET,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = pas_id,
> +			.u.value.b = mem_size,
> +		},
> +		[1] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = lower_32_bits(mem_phys),
> +			.u.value.b = upper_32_bits(mem_phys),
> +		},
> +		/* Reserved for fw memory space to be shared or lent */

Can you explain this comment a bit more? Plan is to allow passing a MEM_REF here
which could be lent/shared to TEE via FFA ABI?

> +		[2] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT,
> +		}
> +	};
> +	int ret;
> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS auth reset failed, pas_id: %d, err: %x\n",
> +			pas_id, inv_arg.ret);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int qcom_pas_tee_auth_and_reset(struct device *dev, u32 pas_id)

I'm guessing once all clients have migrated to PAS, plan is to drop this wrapper?

> +{
> +	return __qcom_pas_tee_auth_and_reset(dev, pas_id, 0, 0);
> +}
> +
> +static int qcom_pas_tee_prepare_and_auth_reset(struct device *dev,
> +					       struct qcom_pas_context *ctx)
> +{
> +	return __qcom_pas_tee_auth_and_reset(dev, ctx->pas_id, ctx->mem_phys,
> +					     ctx->mem_size);
> +}
> +
> +static int qcom_pas_tee_set_remote_state(struct device *dev, u32 state,
> +					 u32 pas_id)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_SET_REMOTE_STATE,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = pas_id,
> +			.u.value.b = state,
> +		}
> +	};
> +	int ret;

Nit: Why not ret = 0 initialize and always use ret?

> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS shutdown failed, pas_id: %d, err: %x\n",
> +			pas_id, inv_arg.ret);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int qcom_pas_tee_shutdown(struct device *dev, u32 pas_id)
> +{
> +	struct qcom_pas_tee_private *data = dev_get_drvdata(dev);
> +	struct tee_ioctl_invoke_arg inv_arg = {
> +		.func = TA_QCOM_PAS_SHUTDOWN,
> +		.session = data->session_id,
> +		.num_params = TEE_NUM_PARAMS
> +	};
> +	struct tee_param param[4] = {
> +		[0] = {
> +			.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
> +			.u.value.a = pas_id
> +		}
> +	};
> +	int ret = 0;
> +
> +	ret = tee_client_invoke_func(data->ctx, &inv_arg, param);
> +	if (ret < 0 || inv_arg.ret != 0) {
> +		dev_err(dev, "PAS shutdown failed, pas_id: %d, err: %x\n",
> +			pas_id, inv_arg.ret);
> +		return -EINVAL;
> +	}
> +
> +	return 0;

You could just return 'ret' here. :)

> +}
> +
> +static void qcom_pas_tee_metadata_release(struct device *dev,
> +					  struct qcom_pas_context *ctx)
> +{
> +	struct tee_shm *mdata_shm = ctx->ptr;
> +

Nit: Unnecessary extra line.

> +	tee_shm_free(mdata_shm);
> +}
> +

[...]

> +
> +module_tee_client_driver(optee_pas_tee_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("TEE bus based Qualcomm PAS driver");

Since this is a tee_client driver, isn't it self-explanatary that it's TEE bus based?



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox