From 0aa10e891e6a9ff3221babd11bcf67ad57fbe2bd Mon Sep 17 00:00:00 2001 From: Wojciech Slenska Date: Thu, 9 Oct 2025 11:07:17 +0200 Subject: [PATCH 01/29] UPSTREAM: arm64: dts: qcom: qcm2290: Fix uart3 QUP interconnect The config_noc interconnect should use SLAVE_QUP_0. Signed-off-by: Wojciech Slenska Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251009090718.32503-1-wojciech.slenska@gmail.com Signed-off-by: Bjorn Andersson (cherry picked from commit cdf9756037d74dee865570e808e4bded7402c662) Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index d947418302674..a4239fc6b71cb 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -1302,7 +1302,7 @@ interconnects = <&qup_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG &qup_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, <&bimc MASTER_APPSS_PROC RPM_ALWAYS_TAG - &config_noc MASTER_APPSS_PROC RPM_ALWAYS_TAG>; + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; interconnect-names = "qup-core", "qup-config"; status = "disabled"; From bd7b5f41a96e651ccea446dd2e35b4336a0014a7 Mon Sep 17 00:00:00 2001 From: Wojciech Slenska Date: Thu, 9 Oct 2025 11:08:58 +0200 Subject: [PATCH 02/29] UPSTREAM: arm64: dts: qcom: qcm2290: Add uart1 and uart5 nodes Add nodes to support uart1 and uart5. Signed-off-by: Wojciech Slenska Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251009090858.32911-1-wojciech.slenska@gmail.com Signed-off-by: Bjorn Andersson (cherry picked from commit 89e4902ac7262f368dfb03afd76d71e6bbb4424d) Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index a4239fc6b71cb..d5af1e5ac05d5 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -552,6 +552,13 @@ bias-disable; }; + qup_uart1_default: qup-uart1-default-state { + pins = "gpio4", "gpio5", "gpio69", "gpio70"; + function = "qup1"; + drive-strength = <2>; + bias-disable; + }; + qup_uart3_default: qup-uart3-default-state { pins = "gpio8", "gpio9", "gpio10", "gpio11"; function = "qup3"; @@ -566,6 +573,13 @@ bias-disable; }; + qup_uart5_default: qup-uart5-default-state { + pins = "gpio14", "gpio15", "gpio16", "gpio17"; + function = "qup5"; + drive-strength = <2>; + bias-disable; + }; + cci0_default: cci0-default-state { pins = "gpio22", "gpio23"; function = "cci_i2c"; @@ -1197,6 +1211,23 @@ status = "disabled"; }; + uart1: serial@4a84000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a84000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>; + clock-names = "se"; + pinctrl-0 = <&qup_uart1_default>; + pinctrl-names = "default"; + interconnects = <&qup_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &qup_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&bimc MASTER_APPSS_PROC RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + status = "disabled"; + }; + i2c2: i2c@4a88000 { compatible = "qcom,geni-i2c"; reg = <0x0 0x04a88000 0x0 0x4000>; @@ -1418,6 +1449,23 @@ #size-cells = <0>; status = "disabled"; }; + + uart5: serial@4a94000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a94000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>; + clock-names = "se"; + pinctrl-0 = <&qup_uart5_default>; + pinctrl-names = "default"; + interconnects = <&qup_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &qup_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&bimc MASTER_APPSS_PROC RPM_ALWAYS_TAG + &config_noc SLAVE_QUP_0 RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + status = "disabled"; + }; }; usb: usb@4ef8800 { From 6f45867d6f1c10abfb9a9a25a4c9f8b36017df50 Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Thu, 20 Nov 2025 16:58:24 +0100 Subject: [PATCH 03/29] BACKPORT: arm64: dts: qcom: agatti: add uart2 node uart2 is used in Arduino UnoQ as an interface between microprocessor and microcontroller. Signed-off-by: Riccardo Mereu Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20251120155825.121483-6-r.mereu.kernel@arduino.cc Signed-off-by: Bjorn Andersson (cherry picked from commit 925ac1f6ec75a773e0ec8b91673b647f6d456ccb) [rsalveti: applied to qcm2290.dtsi, as the rename to agatti.dtsi is not part of this branch] Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index d5af1e5ac05d5..5406286db8509 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -559,6 +559,13 @@ bias-disable; }; + qup_uart2_default: qup-uart2-default-state { + pins = "gpio6", "gpio7", "gpio71", "gpio80"; + function = "qup2"; + drive-strength = <2>; + bias-disable; + }; + qup_uart3_default: qup-uart3-default-state { pins = "gpio8", "gpio9", "gpio10", "gpio11"; function = "qup3"; @@ -1275,6 +1282,23 @@ status = "disabled"; }; + uart2: serial@4a88000 { + compatible = "qcom,geni-uart"; + reg = <0x0 0x04a88000 0x0 0x4000>; + interrupts = ; + clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>; + clock-names = "se"; + pinctrl-0 = <&qup_uart2_default>; + pinctrl-names = "default"; + interconnects = <&qup_virt MASTER_QUP_CORE_0 RPM_ALWAYS_TAG + &qup_virt SLAVE_QUP_CORE_0 RPM_ALWAYS_TAG>, + <&bimc MASTER_APPSS_PROC RPM_ALWAYS_TAG + &config_noc MASTER_APPSS_PROC RPM_ALWAYS_TAG>; + interconnect-names = "qup-core", + "qup-config"; + status = "disabled"; + }; + i2c3: i2c@4a8c000 { compatible = "qcom,geni-i2c"; reg = <0x0 0x04a8c000 0x0 0x4000>; From d3c48957b4f7c31e567f3a2c1408acc396a19149 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 28 Oct 2025 23:00:06 +0200 Subject: [PATCH 04/29] BACKPORT: arm64: dts: qcom: add gpu_zap_shader label Patching existing DT nodes based on full path is error prone and generally not recommended. Follow the pattern introduced in the last platforms, add gpu_zap_shader label to the ZAP node and use it in the board files. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Reviewed-by: David Heidelberg Link: https://lore.kernel.org/r/20251028-dt-zap-shader-v1-7-7eccb823b986@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit 2377626fd216ebdf17294ac0cabc27614fff07d1) [rsalveti: only the qcm2290 hunk is backported, as the label is required by the Arduino UNO Q board DT; the other platforms are left untouched to avoid churn on boards that do not need it] Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index 5406286db8509..46bf9912ef916 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -1612,7 +1612,7 @@ status = "disabled"; - zap-shader { + gpu_zap_shader: zap-shader { memory-region = <&pil_gpu_mem>; }; From 08837e54ed1ed379b44d66932c0b0c4ce88f95c6 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 22 Oct 2025 07:06:41 +0100 Subject: [PATCH 05/29] UPSTREAM: arm64: dts: qcom: qcm2290: add APR and its services Add APR (asynchronous packet router) node and its associated services required to enable audio on QRB2210 RB1 board. Cc: Srinivas Kandagatla Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Alexey Klimov Link: https://lore.kernel.org/r/20251022-rb1_hdmi_audio-v3-1-0d38f777a547@linaro.org Signed-off-by: Bjorn Andersson (cherry picked from commit f8d21b5e4caa7a8e06cf6c08d85f6e992562a667) Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 72 +++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index 46bf9912ef916..7f2588b609eb6 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -17,6 +17,8 @@ #include #include #include +#include +#include / { interrupt-parent = <&intc>; @@ -2157,6 +2159,76 @@ label = "lpass"; qcom,remote-pid = <2>; mboxes = <&apcs_glb 8>; + + apr { + compatible = "qcom,apr-v2"; + qcom,glink-channels = "apr_audio_svc"; + qcom,domain = ; + #address-cells = <1>; + #size-cells = <0>; + + service@3 { + reg = ; + compatible = "qcom,q6core"; + qcom,protection-domain = "avs/audio", + "msm/adsp/audio_pd"; + }; + + q6afe: service@4 { + compatible = "qcom,q6afe"; + reg = ; + qcom,protection-domain = "avs/audio", + "msm/adsp/audio_pd"; + q6afedai: dais { + compatible = "qcom,q6afe-dais"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <1>; + }; + + q6afecc: clock-controller { + compatible = "qcom,q6afe-clocks"; + #clock-cells = <2>; + }; + }; + + q6asm: service@7 { + compatible = "qcom,q6asm"; + reg = ; + qcom,protection-domain = "avs/audio", + "msm/adsp/audio_pd"; + q6asmdai: dais { + compatible = "qcom,q6asm-dais"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <1>; + iommus = <&apps_smmu 0x1c1 0x0>; + + dai@0 { + reg = ; + }; + + dai@1 { + reg = ; + }; + + dai@2 { + reg = ; + }; + }; + }; + + q6adm: service@8 { + compatible = "qcom,q6adm"; + reg = ; + qcom,protection-domain = "avs/audio", + "msm/adsp/audio_pd"; + q6routing: routing { + compatible = "qcom,q6adm-routing"; + #sound-dai-cells = <0>; + }; + }; + }; }; }; From 849e9f6e929ada0834dc6ede1ade52ef48c16abf Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 13 Jan 2026 18:41:59 +0200 Subject: [PATCH 06/29] BACKPORT: arm64: dts: qcom: agatti: enable FastRPC on the ADSP On Agatti platform the ADSP provides FastRPC support. Add corresponding device node, in order to be able to utilize the DSP offload from the Linux side. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260113-agatti-fastrpc-v2-1-b66870213f89@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit 851d5ae6003b6517fb641675c33d4b529765fe14) [rsalveti: applied to qcm2290.dtsi, as the rename to agatti.dtsi is not part of this branch] Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index 7f2588b609eb6..e52dbd2fdaf70 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -2229,6 +2229,47 @@ }; }; }; + + fastrpc { + compatible = "qcom,fastrpc"; + qcom,glink-channels = "fastrpcglink-apps-dsp"; + label = "adsp"; + + qcom,non-secure-domain; + + #address-cells = <1>; + #size-cells = <0>; + + compute-cb@3 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <3>; + iommus = <&apps_smmu 0x1c3 0x0>; + }; + + compute-cb@4 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <4>; + iommus = <&apps_smmu 0x1c4 0x0>; + }; + + compute-cb@5 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <5>; + iommus = <&apps_smmu 0x1c5 0x0>; + }; + + compute-cb@6 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <6>; + iommus = <&apps_smmu 0x1c6 0x0>; + }; + + compute-cb@7 { + compatible = "qcom,fastrpc-compute-cb"; + reg = <7>; + iommus = <&apps_smmu 0x1c7 0x0>; + }; + }; }; }; From 7fa4a098d560b715de1ecb968f662267a05ac155 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Tue, 7 Oct 2025 03:03:29 +0100 Subject: [PATCH 07/29] UPSTREAM: dt-bindings: pinctrl: qcom,sm6115-lpass-lpi: add QCM2290 compatible Add a compatible for the LPASS LPI pin controller on QCM2290. It seems to be compatible with sm6115 LPASS pinctrl. Cc: Konrad Dybcio Cc: Srinivas Kandagatla Acked-by: Rob Herring (Arm) Signed-off-by: Alexey Klimov Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20251007-rb1_hdmi_audio-v2-1-821b6a705e4c@linaro.org (cherry picked from commit f919466878611065afb0b79feb28969af766ef3f) Signed-off-by: Ricardo Salveti --- .../bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml index f4cf2ce86fcd4..ec1cd684753ad 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-lpass-lpi-pinctrl.yaml @@ -16,7 +16,13 @@ description: properties: compatible: - const: qcom,sm6115-lpass-lpi-pinctrl + oneOf: + - enum: + - qcom,sm6115-lpass-lpi-pinctrl + - items: + - enum: + - qcom,qcm2290-lpass-lpi-pinctrl + - const: qcom,sm6115-lpass-lpi-pinctrl reg: items: From cc36cef652b20662789462b64769a6eb432c50fe Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Wed, 22 Oct 2025 07:06:42 +0100 Subject: [PATCH 08/29] UPSTREAM: arm64: dts: qcom: qcm2290: add LPASS LPI pin controller Add the Low Power Audio SubSystem Low Power Island (LPASS LPI) pin controller device node required for audio subsystem on Qualcomm QRB2210 RB1. QRB2210 is based on qcm2290 which is based on sm6115. While at this, also add description of lpi_i2s2 pins (active state) required for audio playback via HDMI/I2S. Cc: Srinivas Kandagatla Signed-off-by: Alexey Klimov Link: https://lore.kernel.org/r/20251022-rb1_hdmi_audio-v3-2-0d38f777a547@linaro.org Signed-off-by: Bjorn Andersson (cherry picked from commit 1fc30731562bb45e53e09d40fc69bc4364310b6e) Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index e52dbd2fdaf70..3e08fde59cf1b 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -19,6 +19,7 @@ #include #include #include +#include / { interrupt-parent = <&intc>; @@ -694,6 +695,43 @@ }; }; + lpass_tlmm: pinctrl@a7c0000 { + compatible = "qcom,qcm2290-lpass-lpi-pinctrl", + "qcom,sm6115-lpass-lpi-pinctrl"; + reg = <0x0 0x0a7c0000 0x0 0x20000>, + <0x0 0x0a950000 0x0 0x10000>; + + clocks = <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>; + clock-names = "audio"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&lpass_tlmm 0 0 19>; + + lpi_i2s2_active: lpi-i2s2-active-state { + sck-pins { + pins = "gpio10"; + function = "i2s2_clk"; + bias-disable; + drive-strength = <8>; + }; + + ws-pins { + pins = "gpio11"; + function = "i2s2_ws"; + bias-disable; + drive-strength = <8>; + }; + + data-pins { + pins = "gpio12"; + function = "i2s2_data"; + bias-disable; + drive-strength = <8>; + }; + }; + }; + gcc: clock-controller@1400000 { compatible = "qcom,gcc-qcm2290"; reg = <0x0 0x01400000 0x0 0x1f0000>; From d7490f149126d30e8a3a5bc377e808660e246dba Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Thu, 7 May 2026 09:42:16 +0300 Subject: [PATCH 09/29] BACKPORT: arm64: dts: qcom: agatti: add higher OPP levels Add additional OPP entries for the Agatti platform to support higher operating frequencies as specified in the hardware documentation. Reviewed-by: Dmitry Baryshkov Signed-off-by: Dikshita Agarwal Link: https://lore.kernel.org/r/20260507-iris-ar50lt-v1-16-d22cccedc3e2@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit f8874bc5792134b7bdda9706e2a48e6285da3664) [rsalveti: applied to qcm2290.dtsi, as the rename to agatti.dtsi is not part of this branch] Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index 3e08fde59cf1b..280bc8a64ef02 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -2433,6 +2433,16 @@ opp-hz = /bits/ 64 <240000000>; required-opps = <&rpmpd_opp_svs>; }; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmpd_opp_svs_plus>; + }; + + opp-384000000 { + opp-hz = /bits/ 64 <384000000>; + required-opps = <&rpmpd_opp_nom>; + }; }; }; From 27f5958bd9930c67b5266129e5b8a30f073382cd Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Sat, 18 Jul 2026 18:26:08 +0530 Subject: [PATCH 10/29] BACKPORT: dt-bindings: clock: qcom,qcm2290-dispcc: Add missing power-domains property Add the missing power-domains property to associate DISPCC with RPMPD_CX. This is to ensure the genpd performance state votes on the GDSC to get propagated to the CX rail and to avoid the rail under-voltage conditions. This change breaks ABI, as the power-domains property is marked as required. Fixes: 85cedb4e0c9d ("dt-bindings: clock: Add qualcomm QCM2290 DISPCC bindings") Reviewed-by: Krzysztof Kozlowski Signed-off-by: Imran Shaik Link: https://lore.kernel.org/r/20260718-shikra-dispcc-gpucc-v6-1-62703e05ef0f@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit 70ef527b483f6373c4b954e81bbb73f3bdc3184a) [rsalveti: keep the DSI1/sleep clocks already present in this branch, and require power-domains only when the compatible is not qcom,shikra-dispcc. Upstream marks it required for every compatible, but this branch also matches qcom,shikra-dispcc against this schema and the Shikra DTs do not describe the CX domain yet, so making it unconditional regresses dtbs_check on shikra-cq{m,s}-evk{,-imx577-camera}] Signed-off-by: Ricardo Salveti --- .../bindings/clock/qcom,qcm2290-dispcc.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml index 5cee033f2115d..2cf58843e54a4 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml @@ -49,6 +49,10 @@ properties: - const: dsi1_phy_pll_out_dsiclk - const: sleep_clk + power-domains: + items: + - description: CX domain + required: - compatible - clocks @@ -57,6 +61,17 @@ required: allOf: - $ref: qcom,gcc.yaml# + # The Shikra variant carried by this branch does not describe the CX domain + # yet, so only demand it on plain qcm2290. + - if: + not: + properties: + compatible: + contains: + const: qcom,shikra-dispcc + then: + required: + - power-domains unevaluatedProperties: false @@ -65,6 +80,7 @@ examples: #include #include #include + #include clock-controller@5f00000 { compatible = "qcom,qcm2290-dispcc"; reg = <0x5f00000 0x20000>; @@ -86,6 +102,7 @@ examples: "dsi1_phy_pll_out_byteclk", "dsi1_phy_pll_out_dsiclk", "sleep_clk"; + power-domains = <&rpmpd RPMPD_VDDCX>; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; From cade1193ed3041cdf37e2b76e46ac0a817c87b53 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Sat, 18 Jul 2026 18:26:19 +0530 Subject: [PATCH 11/29] BACKPORT: arm64: dts: qcom: agatti: Add missing CX power domain to DISPCC Add the missing power-domains property to associate DISPCC with CX rail. This is to ensure the genpd performance state votes on the GDSC to get propagated to the CX rail and to avoid the rail under-voltage conditions. Fixes: a2b32096709d ("arm64: dts: qcom: qcm2290: Add display nodes") Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Imran Shaik Link: https://lore.kernel.org/r/20260718-shikra-dispcc-gpucc-v6-12-62703e05ef0f@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit 26d7b23caa4b1d8208e28c5981a85cf83e658e7c) [rsalveti: applied to qcm2290.dtsi, keeping the DSI1/sleep clocks already present in this branch] Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qcm2290.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi index 280bc8a64ef02..7eaba1edd1f22 100644 --- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi +++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi @@ -2122,6 +2122,7 @@ "dsi1_phy_pll_out_byteclk", "dsi1_phy_pll_out_dsiclk", "sleep_clk"; + power-domains = <&rpmpd QCM2290_VDDCX>; #power-domain-cells = <1>; #clock-cells = <1>; #reset-cells = <1>; From f5f983b3c6a544b91af848017090e6c4ba1e6eb1 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 29 Dec 2025 21:47:39 +0100 Subject: [PATCH 12/29] UPSTREAM: dt-bindings: display/msm/gpu: Straighten out reg-names on A619L/610/702 These GPUs have physically have the same regions as the base case ("main" + "cx_mem" + "cx_dbgc"). Remove the specific override. Signed-off-by: Konrad Dybcio Acked-by: Rob Herring (Arm) Patchwork: https://patchwork.freedesktop.org/patch/696547/ Message-ID: <20251229-topic-6115_2290_gpu_dbgc-v1-1-4a24d196389c@oss.qualcomm.com> Signed-off-by: Rob Clark Link: https://lore.kernel.org/r/20251229-topic-6115_2290_gpu_dbgc-v1-1-4a24d196389c@oss.qualcomm.com (cherry picked from commit ae26b4d513347aa247772a26f374b66d30af550e) Signed-off-by: Ricardo Salveti --- Documentation/devicetree/bindings/display/msm/gpu.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/gpu.yaml b/Documentation/devicetree/bindings/display/msm/gpu.yaml index 2186af7a9d75a..d0f5cff3286ef 100644 --- a/Documentation/devicetree/bindings/display/msm/gpu.yaml +++ b/Documentation/devicetree/bindings/display/msm/gpu.yaml @@ -380,12 +380,6 @@ allOf: - const: xo description: GPUCC clocksource clock - reg-names: - minItems: 1 - items: - - const: kgsl_3d0_reg_memory - - const: cx_dbgc - required: - clocks - clock-names From a2f6bca8536556f4df0ec62e1d286d52e7bea60d Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Thu, 20 Nov 2025 16:58:20 +0100 Subject: [PATCH 13/29] UPSTREAM: dt-bindings: vendor-prefixes: Add Arduino name Add entry for Arduino SRL (https://arduino.cc) Signed-off-by: Riccardo Mereu Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20251120155825.121483-2-r.mereu.kernel@arduino.cc Signed-off-by: Bjorn Andersson (cherry picked from commit d16ffac771715a8c94611b6f8088a3e800bcf5bf) Signed-off-by: Ricardo Salveti --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 7fa32190761b6..5c46fe72204b0 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -154,6 +154,8 @@ patternProperties: description: Arctic Sand "^arcx,.*": description: arcx Inc. / Archronix Inc. + "^arduino,.*": + description: Arduino SRL "^argon40,.*": description: Argon 40 Technologies Limited "^ariaboard,.*": From 0048212bf6cbd24f7a9cde559634ba727842e92e Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Thu, 20 Nov 2025 16:58:23 +0100 Subject: [PATCH 14/29] UPSTREAM: dt-bindings: arm: qcom: Add arduino imola, UnoQ codename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document Arduino imola, UnoQ codename. Arduino UnoQ combines Qualcomm Dragonwing™ QRB2210 microprocessor with STMicroelectronics STM32U585 microcontroller. Signed-off-by: Riccardo Mereu Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20251120155825.121483-5-r.mereu.kernel@arduino.cc Signed-off-by: Bjorn Andersson (cherry picked from commit 311d173da672397a58498841299ec613ff9eb96b) Signed-off-by: Ricardo Salveti --- 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 f0359455dc205..580c79f301bf8 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -341,6 +341,7 @@ properties: - description: Qualcomm Technologies, Inc. Robotics RB1 items: - enum: + - arduino,imola - qcom,qrb2210-rb1 - const: qcom,qrb2210 - const: qcom,qcm2290 From 496aeedf2a4cac4f81d7e830a87ba9c1da49c14e Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Thu, 20 Nov 2025 16:58:21 +0100 Subject: [PATCH 15/29] UPSTREAM: dt-bindings: trivial-devices: add arduino spi mcu interface Add unoq mcu interface. It describes an iterface between Qualcomm QRB2210 microprocessor and STMicroelectronics STM32U585 microcontroller on Arduino UnoQ single-board computer. This is a trivial device since it's usage is handled in user space by the arduino-router service. Signed-off-by: Riccardo Mereu Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20251120155825.121483-3-r.mereu.kernel@arduino.cc Signed-off-by: Mark Brown (cherry picked from commit a7bde7c10902a0f6f903d3bbe67461f2b402a9ca) Signed-off-by: Ricardo Salveti --- Documentation/devicetree/bindings/trivial-devices.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 58ff948d93c96..9bff5f0201082 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -53,6 +53,8 @@ properties: - adi,lt7182s # AMS iAQ-Core VOC Sensor - ams,iaq-core + # Arduino microcontroller interface over SPI on UnoQ board + - arduino,unoq-mcu # Temperature monitoring of Astera Labs PT5161L PCIe retimer - asteralabs,pt5161l # i2c h/w elliptic curve crypto module From 2f2ffd9a0cf095372d1145064e0f87463444fe5f Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Thu, 20 Nov 2025 16:58:22 +0100 Subject: [PATCH 16/29] UPSTREAM: spi: spidev: add compatible for arduino spi mcu interface Add compatible entry in spidev describing in Arduino UnoQ single-board computer the interface between Qualcomm QRB2210 microprocessor and STMicroelectronics STM32U585 microcontroller. It is handled in user space by the arduino-router service. Signed-off-by: Riccardo Mereu Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20251120155825.121483-4-r.mereu.kernel@arduino.cc Signed-off-by: Mark Brown (cherry picked from commit 43a3adb6dd39d98bf84e04569e7604be5e5c0d79) Signed-off-by: Ricardo Salveti --- drivers/spi/spidev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 4d53c394101a4..f28528ed1c24e 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -686,6 +686,7 @@ static const struct class spidev_class = { */ static const struct spi_device_id spidev_spi_ids[] = { { .name = /* abb */ "spi-sensor" }, + { .name = /* arduino */ "unoq-mcu" }, { .name = /* cisco */ "spi-petra" }, { .name = /* dh */ "dhcom-board" }, { .name = /* elgin */ "jg10309-01" }, @@ -719,6 +720,7 @@ static int spidev_of_check(struct device *dev) static const struct of_device_id spidev_dt_ids[] = { { .compatible = "abb,spi-sensor", .data = &spidev_of_check }, + { .compatible = "arduino,unoq-mcu", .data = &spidev_of_check }, { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, { .compatible = "dh,dhcom-board", .data = &spidev_of_check }, { .compatible = "elgin,jg10309-01", .data = &spidev_of_check }, From 37a952920fcbdaa1f4a65a712d78bd890e619af9 Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Thu, 20 Nov 2025 16:58:25 +0100 Subject: [PATCH 17/29] BACKPORT: arm64: dts: qcom: qrb2210: add dts for Arduino unoq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arduino UnoQ is a single-board computer combining Qualcomm Dragonwing™ QRB2210 microprocessor with STMicroelectronics STM32U585 microcontroller. Support to a simply boot to shell environment includes: - UART, I2C, SPI - onboard LEDS - eMMC - WLAN and BT Signed-off-by: Riccardo Mereu Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20251120155825.121483-7-r.mereu.kernel@arduino.cc Signed-off-by: Bjorn Andersson (cherry picked from commit 3f745bc0f11f66465e3fa19eb0c808c5b39cb0e5) [rsalveti: include qcm2290.dtsi, as the rename to agatti.dtsi is not part of this branch] Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/Makefile | 1 + .../boot/dts/qcom/qrb2210-arduino-imola.dts | 459 ++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index 9056576bdf7bc..c7de091a5864d 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -220,6 +220,7 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qcs9100-ride-r3-el2.dtb dtb-$(CONFIG_ARCH_QCOM) += qdu1000-idp.dtb +dtb-$(CONFIG_ARCH_QCOM) += qrb2210-arduino-imola.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb2210-rb1.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb4210-rb2.dtb dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts new file mode 100644 index 0000000000000..ae6dd13eb89e7 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2025, Arduino SRL + */ + +/dts-v1/; + +#include +#include "qcm2290.dtsi" +#include "pm4125.dtsi" + +/delete-node/ &cont_splash_memory; + +/ { + model = "Arduino UnoQ"; + compatible = "arduino,imola", "qcom,qrb2210", "qcom,qcm2290"; + chassis-type = "embedded"; + + aliases { + serial0 = &uart4; + serial1 = &uart2; + serial2 = &uart3; + sdhc1 = &sdhc_1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + label = "gpio-keys"; + pinctrl-0 = <&key_volp_n>, <&key_vold_n>; + pinctrl-names = "default"; + + key-volume-up { + label = "Volume Up"; + linux,code = ; + gpios = <&tlmm 96 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + wakeup-source; + }; + + key-volume-down { + label = "Volume Down"; + linux,code = ; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + debounce-interval = <15>; + linux,can-disable; + wakeup-source; + }; + }; + + leds: leds { + compatible = "gpio-leds"; + + led-bt { + label = "unoq:bt-blue2"; + function = LED_FUNCTION_BLUETOOTH; + color = ; + gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "bluetooth-power"; + default-state = "off"; + }; + + led-panic { + label = "unoq:panic-red2"; + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&tlmm 39 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + default-state = "off"; + panic-indicator; + }; + + led-wlan { + label = "unoq:wlan-green2"; + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&tlmm 40 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tx"; + default-state = "off"; + }; + + ledb: led-user-blue { + label = "unoq:user-blue1"; + gpios = <&tlmm 60 GPIO_ACTIVE_HIGH>; + color = ; + }; + + ledg: led-user-green { + label = "unoq:user-green1"; + gpios = <&tlmm 42 GPIO_ACTIVE_HIGH>; + color = ; + }; + + ledr: led-user-red { + label = "unoq:user-red1"; + gpios = <&tlmm 41 GPIO_ACTIVE_HIGH>; + color = ; + }; + }; + + multi-led { + compatible = "leds-group-multicolor"; + color = ; + function = LED_FUNCTION_INDICATOR; + leds = <&ledr>, <&ledg>, <&ledb>; + }; + + /* PM4125 charger out, supplied by VBAT */ + vph_pwr: regulator-vph-pwr { + compatible = "regulator-fixed"; + regulator-name = "vph_pwr"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + regulator-always-on; + regulator-boot-on; + }; +}; + +&gpi_dma0 { + status = "okay"; +}; + +&gpu { + status = "okay"; +}; + +&gpu_zap_shader { + firmware-name = "qcom/qcm2290/a702_zap.mbn"; +}; + +&i2c0 { + clock-frequency = <100000>; + + status = "okay"; +}; + +&i2c1 { + clock-frequency = <100000>; + + status = "okay"; +}; + +&pm4125_vbus { + regulator-min-microamp = <500000>; + regulator-max-microamp = <500000>; + + status = "okay"; +}; + +&qupv3_id_0 { + status = "okay"; +}; + +&remoteproc_adsp { + firmware-name = "qcom/qcm2290/adsp.mbn"; + + status = "okay"; +}; + +&remoteproc_mpss { + firmware-name = "qcom/qcm2290/modem.mbn"; + + status = "okay"; +}; + +&rpm_requests { + regulators { + compatible = "qcom,rpm-pm2250-regulators"; + vdd_s3-supply = <&vph_pwr>; + vdd_s4-supply = <&vph_pwr>; + vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12-supply = <&pm4125_s3>; + vdd_l4_l17_l18_l19_l20_l21_l22-supply = <&vph_pwr>; + vdd_l13_l14_l15_l16-supply = <&pm4125_s4>; + + pm4125_s3: s3 { + /* 0.4V-1.6625V -> 1.3V (Power tree requirements) */ + regulator-min-microvolt = <1352000>; + regulator-max-microvolt = <1352000>; + regulator-boot-on; + }; + + pm4125_s4: s4 { + /* 1.2V-2.35V -> 2.05V (Power tree requirements) */ + regulator-min-microvolt = <2072000>; + regulator-max-microvolt = <2072000>; + regulator-boot-on; + }; + + pm4125_l2: l2 { + /* LPDDR4X VDD2 */ + regulator-min-microvolt = <1136000>; + regulator-max-microvolt = <1136000>; + regulator-always-on; + regulator-boot-on; + }; + + pm4125_l3: l3 { + /* LPDDR4X VDDQ */ + regulator-min-microvolt = <616000>; + regulator-max-microvolt = <616000>; + regulator-always-on; + regulator-boot-on; + }; + + pm4125_l4: l4 { + /* max = 3.05V -> max = 2.7 to disable 3V signaling (SDHCI2) */ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2700000>; + regulator-allow-set-load; + }; + + pm4125_l5: l5 { + /* CSI/DSI */ + regulator-min-microvolt = <1232000>; + regulator-max-microvolt = <1232000>; + regulator-allow-set-load; + regulator-boot-on; + }; + + pm4125_l6: l6 { + /* DRAM PLL */ + regulator-min-microvolt = <928000>; + regulator-max-microvolt = <928000>; + regulator-always-on; + regulator-boot-on; + }; + + pm4125_l7: l7 { + /* Wi-Fi CX */ + regulator-min-microvolt = <664000>; + regulator-max-microvolt = <664000>; + }; + + pm4125_l10: l10 { + /* Wi-Fi RFA */ + regulator-min-microvolt = <1304000>; + regulator-max-microvolt = <1304000>; + }; + + pm4125_l11: l11 { + /* ANX7625 DVDD1P0V/AVDD1P0V */ + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + regulator-always-on; + }; + + pm4125_l12: l12 { + /* USB PHYs */ + regulator-min-microvolt = <928000>; + regulator-max-microvolt = <928000>; + regulator-allow-set-load; + regulator-boot-on; + }; + + pm4125_l13: l13 { + /* USB/QFPROM/PLLs */ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-allow-set-load; + regulator-boot-on; + }; + + pm4125_l14: l14 { + /* SDHCI1 EMMC VCCQ */ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-allow-set-load; + /* Broken hardware, never turn it off! */ + regulator-always-on; + }; + + pm4125_l15: l15 { + /* VDDIO */ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-allow-set-load; + regulator-always-on; + regulator-boot-on; + }; + + pm4125_l20: l20 { + /* SDHCI1 EMMC */ + regulator-min-microvolt = <2400000>; + regulator-max-microvolt = <3600000>; + regulator-allow-set-load; + }; + + pm4125_l21: l21 { + /* USB HS */ + regulator-min-microvolt = <2960000>; + regulator-max-microvolt = <3300000>; + regulator-allow-set-load; + regulator-boot-on; + }; + + pm4125_l22: l22 { + /* Wi-Fi VDD */ + regulator-min-microvolt = <3312000>; + regulator-max-microvolt = <3312000>; + }; + }; +}; + +&sdhc_1 { + vmmc-supply = <&pm4125_l20>; + vqmmc-supply = <&pm4125_l14>; + pinctrl-0 = <&sdc1_state_on>; + pinctrl-1 = <&sdc1_state_off>; + pinctrl-names = "default", "sleep"; + mmc-hs400-1_8v; + mmc-hs200-1_8v; + non-removable; + supports-cqe; + no-sdio; + no-sd; + + status = "okay"; +}; + +&spi5 { + status = "okay"; + + spidev@0 { + reg = <0>; + compatible = "arduino,unoq-mcu"; + pinctrl-0 = <&spidev_cs>; + pinctrl-names = "default"; + }; +}; + +&tlmm { + spidev_cs: spidev-cs-state { + pins = "gpio17"; + function = "gpio"; + drive-strength = <16>; + }; + + jmisc_gpio18: jmisc-gpio18-state { + pins = "gpio18"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + jmisc_gpio28: jmisc-gpio28-state { + pins = "gpio28"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + key_vold_n: key-vold-n-state { + pins = "gpio36"; + function = "gpio"; + bias-pull-up; + output-disable; + }; + + key_volp_n: key-volp-n-state { + pins = "gpio96"; + function = "gpio"; + bias-pull-up; + output-disable; + }; + + jmisc_gpio98: jmisc-gpio98-state { + pins = "gpio98"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + jmisc_gpio99: jmisc-gpio99-state { + pins = "gpio99"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + jmisc_gpio100: jmisc-gpio100-state { + pins = "gpio100"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; + + jmisc_gpio101: jmisc-gpio101-state { + pins = "gpio101"; + function = "gpio"; + drive-strength = <2>; + bias-pull-down; + }; +}; + +&uart2 { + status = "okay"; +}; + +/* UART connected to Bluetooth */ +&uart3 { + status = "okay"; + + bluetooth { + compatible = "qcom,wcn3988-bt"; + + vddio-supply = <&pm4125_l15>; + vddxo-supply = <&pm4125_l13>; + vddrf-supply = <&pm4125_l10>; + vddch0-supply = <&pm4125_l22>; + enable-gpios = <&tlmm 87 GPIO_ACTIVE_HIGH>; + max-speed = <3000000>; + }; +}; + +/* UART exposed in JCTL */ +&uart4 { + compatible = "qcom,geni-debug-uart"; + + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_hsphy { + vdd-supply = <&pm4125_l12>; + vdda-pll-supply = <&pm4125_l13>; + vdda-phy-dpdm-supply = <&pm4125_l21>; + + status = "okay"; +}; + +&usb_qmpphy { + vdda-phy-supply = <&pm4125_l12>; + vdda-pll-supply = <&pm4125_l13>; + + status = "okay"; +}; + +&wifi { + vdd-0.8-cx-mx-supply = <&pm4125_l7>; + vdd-1.8-xo-supply = <&pm4125_l13>; + vdd-1.3-rfa-supply = <&pm4125_l10>; + vdd-3.3-ch0-supply = <&pm4125_l22>; + qcom,ath10k-calibration-variant = "ArduinoImola"; + firmware-name = "qcm2290"; + + status = "okay"; +}; + +&xo_board { + clock-frequency = <38400000>; +}; From 37ef45c997a917fb9e64de86262efb725e62ab82 Mon Sep 17 00:00:00 2001 From: Riccardo Mereu Date: Fri, 13 Feb 2026 11:10:02 +0100 Subject: [PATCH 18/29] UPSTREAM: arm64: dts: qcom: arduino-imola: fix faulty spidev node CS pin added on pinctrl0 property is causing spidev to return -ENODEV since that GPIO is already part of spi5 pinmuxing. Fixes: 3f745bc0f11f ("arm64: dts: qcom: qrb2210: add dts for Arduino unoq") Signed-off-by: Riccardo Mereu Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260213101002.105238-1-r.mereu.kernel@arduino.cc Signed-off-by: Bjorn Andersson (cherry picked from commit 1a040df09fab28b31399fce14a76455b536a2b08) Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts index ae6dd13eb89e7..2e9f26ed2f39f 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -325,21 +325,13 @@ &spi5 { status = "okay"; - spidev@0 { - reg = <0>; + mcu@0 { compatible = "arduino,unoq-mcu"; - pinctrl-0 = <&spidev_cs>; - pinctrl-names = "default"; + reg = <0>; }; }; &tlmm { - spidev_cs: spidev-cs-state { - pins = "gpio17"; - function = "gpio"; - drive-strength = <16>; - }; - jmisc_gpio18: jmisc-gpio18-state { pins = "gpio18"; function = "gpio"; From 0f2977d2dad1c9f52967879b853107240435340e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 21 Jan 2026 12:15:45 +0200 Subject: [PATCH 19/29] UPSTREAM: dt-bindings: drm/bridge: anx7625: describe Type-C connector ANX7625 can be used to mux converted video stream with the USB signals on a Type-C connector. Describe the optional connector subnode, make it exclusive with the AUX bus and port@1 as it is impossible to have both eDP panel and USB-C connector. Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260121-anx7625-typec-v2-1-d14f31256a17@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov (cherry picked from commit 1d7532444a32b53ff7344dc52019bab5a4b5ed66) Signed-off-by: Ricardo Salveti --- .../display/bridge/analogix,anx7625.yaml | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml index a1ed1004651b9..6ad466952c02d 100644 --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml @@ -85,6 +85,11 @@ properties: aux-bus: $ref: /schemas/display/dp-aux-bus.yaml# + connector: + type: object + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -117,7 +122,6 @@ properties: required: - port@0 - - port@1 required: - compatible @@ -127,6 +131,28 @@ required: - vdd33-supply - ports +allOf: + - if: + required: + - aux-bus + - connector + then: + false + + - if: + required: + - connector + then: + properties: + ports: + properties: + port@1: false + else: + properties: + ports: + required: + - port@1 + additionalProperties: false examples: @@ -185,3 +211,73 @@ examples: }; }; }; + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + encoder@58 { + compatible = "analogix,anx7625"; + reg = <0x58>; + enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>; + vdd10-supply = <&pp1000_mipibrdg>; + vdd18-supply = <&pp1800_mipibrdg>; + vdd33-supply = <&pp3300_mipibrdg>; + analogix,audio-enable; + analogix,lane0-swing = /bits/ 8 <0x14 0x54 0x64 0x74>; + analogix,lane1-swing = /bits/ 8 <0x14 0x54 0x64 0x74>; + + connector { + compatible = "usb-c-connector"; + power-role = "dual"; + data-role = "dual"; + vbus-supply = <&vbus_reg>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + remote-endpoint = <&usb_hs>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + remote-endpoint = <&usb_ss>; + }; + }; + + port@2 { + reg = <2>; + + endpoint { + remote-endpoint = <&usb_sbu>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + endpoint { + remote-endpoint = <&mipi_dsi>; + bus-type = <7>; + data-lanes = <0 1 2 3>; + }; + }; + }; + }; + }; From c32adf14e28e281cfa4645ed00b9721d072e46f0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 21 Jan 2026 12:15:46 +0200 Subject: [PATCH 20/29] UPSTREAM: drm: bridge: anx7625: implement minimal Type-C support ANX7625 can be used as a USB-C controller, handling USB and DP data streams. Provide minimal Type-C support necessary for ANX7625 to register the Type-C port device and properly respond to data / power role events from the Type-C partner. While ANX7625 provides TCPCI interface, using it would circumvent the on-chip running firmware. Analogix recommended using the higher-level interface instead of TCPCI. Reviewed-by: Xin Ji Reviewed-by: Heikki Krogerus Link: https://patch.msgid.link/20260121-anx7625-typec-v2-2-d14f31256a17@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov (cherry picked from commit f81455b2d3327a5685623e7db4050dbbe5513bc3) Signed-off-by: Ricardo Salveti --- drivers/gpu/drm/bridge/analogix/Kconfig | 1 + drivers/gpu/drm/bridge/analogix/anx7625.c | 155 ++++++++++++++++++++-- drivers/gpu/drm/bridge/analogix/anx7625.h | 22 ++- 3 files changed, 168 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index 4846b2e9be7c2..f3448b0631fea 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -34,6 +34,7 @@ config DRM_ANALOGIX_ANX7625 tristate "Analogix Anx7625 MIPI to DP interface support" depends on DRM depends on OF + depends on TYPEC || !TYPEC select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 836b29fdc8479..423dff131e907 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -3,6 +3,7 @@ * Copyright(c) 2020, Analogix Semiconductor. All rights reserved. * */ +#include #include #include #include @@ -15,6 +16,9 @@ #include #include #include +#include +#include +#include #include #include @@ -1325,7 +1329,7 @@ static int anx7625_read_hpd_gpio_config_status(struct anx7625_data *ctx) static void anx7625_disable_pd_protocol(struct anx7625_data *ctx) { struct device *dev = ctx->dev; - int ret, val; + int ret; /* Reset main ocm */ ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client, 0x88, 0x40); @@ -1339,6 +1343,11 @@ static void anx7625_disable_pd_protocol(struct anx7625_data *ctx) DRM_DEV_DEBUG_DRIVER(dev, "disable PD feature fail.\n"); else DRM_DEV_DEBUG_DRIVER(dev, "disable PD feature succeeded.\n"); +} + +static void anx7625_configure_hpd(struct anx7625_data *ctx) +{ + int val; /* * Make sure the HPD GPIO already be configured after OCM release before @@ -1369,7 +1378,9 @@ static int anx7625_ocm_loading_check(struct anx7625_data *ctx) if ((ret & FLASH_LOAD_STA_CHK) != FLASH_LOAD_STA_CHK) return -ENODEV; - anx7625_disable_pd_protocol(ctx); + if (!ctx->typec_port) + anx7625_disable_pd_protocol(ctx); + anx7625_configure_hpd(ctx); DRM_DEV_DEBUG_DRIVER(dev, "Firmware ver %02x%02x,", anx7625_reg_read(ctx, @@ -1472,6 +1483,107 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx) DRM_DEV_DEBUG_DRIVER(dev, "Secure OCM version=%02x\n", ret); } +#if IS_REACHABLE(CONFIG_TYPEC) +static void anx7625_typec_set_orientation(struct anx7625_data *ctx) +{ + u32 val = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); + + if (val & (CC1_RP | CC1_RD)) + typec_set_orientation(ctx->typec_port, TYPEC_ORIENTATION_NORMAL); + else if (val & (CC2_RP | CC2_RD)) + typec_set_orientation(ctx->typec_port, TYPEC_ORIENTATION_REVERSE); + else + typec_set_orientation(ctx->typec_port, TYPEC_ORIENTATION_NONE); +} + +static void anx7625_typec_set_status(struct anx7625_data *ctx, + unsigned int intr_status, + unsigned int intr_vector) +{ + if (intr_vector & CC_STATUS) + anx7625_typec_set_orientation(ctx); + if (intr_vector & DATA_ROLE_STATUS) { + enum typec_data_role data_role = (intr_status & DATA_ROLE_STATUS) ? + TYPEC_HOST : TYPEC_DEVICE; + usb_role_switch_set_role(ctx->role_sw, + (intr_status & DATA_ROLE_STATUS) ? + USB_ROLE_HOST : USB_ROLE_DEVICE); + typec_set_data_role(ctx->typec_port, data_role); + ctx->typec_data_role = data_role; + } + if (intr_vector & VBUS_STATUS) + typec_set_pwr_role(ctx->typec_port, + (intr_status & VBUS_STATUS) ? + TYPEC_SOURCE : TYPEC_SINK); + if (intr_vector & VCONN_STATUS) + typec_set_vconn_role(ctx->typec_port, + (intr_status & VCONN_STATUS) ? + TYPEC_SOURCE : TYPEC_SINK); +} + +static int anx7625_typec_register(struct anx7625_data *ctx) +{ + struct typec_capability typec_cap = { }; + struct fwnode_handle *fwnode __free(fwnode_handle) = + device_get_named_child_node(ctx->dev, "connector"); + u32 val; + int ret; + + if (!fwnode) + return 0; + + ret = typec_get_fw_cap(&typec_cap, fwnode); + if (ret < 0) + return ret; + + typec_cap.revision = 0x0120; + typec_cap.pd_revision = 0x0300; + typec_cap.usb_capability = USB_CAPABILITY_USB2 | USB_CAPABILITY_USB3; + typec_cap.orientation_aware = true; + + typec_cap.driver_data = ctx; + + ctx->typec_port = typec_register_port(ctx->dev, &typec_cap); + if (IS_ERR(ctx->typec_port)) + return PTR_ERR(ctx->typec_port); + + ctx->role_sw = fwnode_usb_role_switch_get(fwnode); + if (IS_ERR(ctx->role_sw)) { + typec_unregister_port(ctx->typec_port); + return PTR_ERR(ctx->role_sw); + } + + val = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); + + anx7625_typec_set_status(ctx, val, + CC_STATUS | DATA_ROLE_STATUS | + VBUS_STATUS | VCONN_STATUS); + + return 0; +} + +static void anx7625_typec_unregister(struct anx7625_data *ctx) +{ + usb_role_switch_put(ctx->role_sw); + typec_unregister_port(ctx->typec_port); +} +#else +static void anx7625_typec_set_status(struct anx7625_data *ctx, + unsigned int intr_status, + unsigned int intr_vector) +{ +} + +static int anx7625_typec_register(struct anx7625_data *ctx) +{ + return 0; +} + +static void anx7625_typec_unregister(struct anx7625_data *ctx) +{ +} +#endif + static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx) { return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); @@ -1566,7 +1678,7 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on) } } -static int anx7625_hpd_change_detect(struct anx7625_data *ctx) +static int anx7625_intr_status(struct anx7625_data *ctx) { int intr_vector, status; struct device *dev = ctx->dev; @@ -1593,9 +1705,6 @@ static int anx7625_hpd_change_detect(struct anx7625_data *ctx) return status; } - if (!(intr_vector & HPD_STATUS_CHANGE)) - return -ENOENT; - status = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); if (status < 0) { @@ -1604,6 +1713,12 @@ static int anx7625_hpd_change_detect(struct anx7625_data *ctx) } DRM_DEV_DEBUG_DRIVER(dev, "0x7e:0x45=%x\n", status); + + anx7625_typec_set_status(ctx, status, intr_vector); + + if (!(intr_vector & HPD_STATUS)) + return -ENOENT; + dp_hpd_change_handler(ctx, status & HPD_STATUS); return 0; @@ -1622,7 +1737,7 @@ static void anx7625_work_func(struct work_struct *work) return; } - event = anx7625_hpd_change_detect(ctx); + event = anx7625_intr_status(ctx); mutex_unlock(&ctx->lock); @@ -2741,11 +2856,29 @@ static int anx7625_i2c_probe(struct i2c_client *client) } if (!platform->pdata.low_power_mode) { - anx7625_disable_pd_protocol(platform); + struct fwnode_handle *fwnode; + + fwnode = device_get_named_child_node(dev, "connector"); + if (fwnode) + fwnode_handle_put(fwnode); + else + anx7625_disable_pd_protocol(platform); + + anx7625_configure_hpd(platform); + pm_runtime_get_sync(dev); _anx7625_hpd_polling(platform, 5000 * 100); } + if (platform->pdata.intp_irq) + anx7625_reg_write(platform, platform->i2c.rx_p0_client, + INTERFACE_CHANGE_INT_MASK, 0); + + /* After getting runtime handle */ + ret = anx7625_typec_register(platform); + if (ret) + goto pm_suspend; + /* Add work function */ if (platform->pdata.intp_irq) { enable_irq(platform->pdata.intp_irq); @@ -2759,6 +2892,10 @@ static int anx7625_i2c_probe(struct i2c_client *client) return 0; +pm_suspend: + if (!platform->pdata.low_power_mode) + pm_runtime_put_sync_suspend(&client->dev); + free_wq: if (platform->workqueue) destroy_workqueue(platform->workqueue); @@ -2774,6 +2911,8 @@ static void anx7625_i2c_remove(struct i2c_client *client) { struct anx7625_data *platform = i2c_get_clientdata(client); + anx7625_typec_unregister(platform); + drm_bridge_remove(&platform->bridge); if (platform->pdata.intp_irq) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h index eb5580f1ab2f8..a18561c213af9 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.h +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h @@ -51,9 +51,21 @@ #define INTR_RECEIVED_MSG BIT(5) #define SYSTEM_STSTUS 0x45 +#define INTERFACE_CHANGE_INT_MASK 0x43 #define INTERFACE_CHANGE_INT 0x44 -#define HPD_STATUS_CHANGE 0x80 -#define HPD_STATUS 0x80 +#define VCONN_STATUS BIT(2) +#define VBUS_STATUS BIT(3) +#define CC_STATUS BIT(4) +#define DATA_ROLE_STATUS BIT(5) +#define HPD_STATUS BIT(7) + +#define NEW_CC_STATUS 0x46 +#define CC1_RD BIT(0) +#define CC1_RA BIT(1) +#define CC1_RP (BIT(2) | BIT(3)) +#define CC2_RD BIT(4) +#define CC2_RA BIT(5) +#define CC2_RP (BIT(6) | BIT(7)) /******** END of I2C Address 0x58 ********/ @@ -447,9 +459,15 @@ struct anx7625_i2c_client { struct i2c_client *tcpc_client; }; +struct typec_port; +struct usb_role_switch; + struct anx7625_data { struct anx7625_platform_data pdata; struct platform_device *audio_pdev; + struct typec_port *typec_port; + struct usb_role_switch *role_sw; + int typec_data_role; int hpd_status; int hpd_high_cnt; int dp_en; From 8da7cb43557b5c30133161a138ae02009e9ac6df Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 21 Jan 2026 12:15:47 +0200 Subject: [PATCH 21/29] UPSTREAM: drm: bridge: anx7625: implement message sending Swapping the data role requires sending the message to the other USB-C side. Implement sending these messages through the OCM. The code is largely based on the anx7411.c USB-C driver. Reviewed-by: Xin Ji Link: https://patch.msgid.link/20260121-anx7625-typec-v2-3-d14f31256a17@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov (cherry picked from commit 8ad0f7d2e6fdfc4462a5b168ec64d73b7e952ab9) Signed-off-by: Ricardo Salveti --- drivers/gpu/drm/bridge/analogix/anx7625.c | 68 +++++++++++++++++++++++ drivers/gpu/drm/bridge/analogix/anx7625.h | 12 ++++ 2 files changed, 80 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 423dff131e907..9410283b84a57 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1484,6 +1484,73 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx) } #if IS_REACHABLE(CONFIG_TYPEC) +static u8 anx7625_checksum(u8 *buf, u8 len) +{ + u8 ret = 0; + u8 i; + + for (i = 0; i < len; i++) + ret += buf[i]; + + return ret; +} + +static int anx7625_read_msg_ctrl_status(struct anx7625_data *ctx) +{ + return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, CMD_SEND_BUF); +} + +static int anx7625_wait_msg_empty(struct anx7625_data *ctx) +{ + int val; + + return readx_poll_timeout(anx7625_read_msg_ctrl_status, ctx, + val, (val < 0) || (val == 0), + 2000, 2000 * 150); +} + +static int anx7625_send_msg(struct anx7625_data *ctx, u8 type, u8 *buf, u8 size) +{ + struct fw_msg *msg = &ctx->send_msg; + u8 crc; + int ret; + + size = min_t(u8, size, (u8)MAX_BUF_LEN); + memcpy(msg->buf, buf, size); + msg->msg_type = type; + + /* msg len equals buffer length + msg_type */ + msg->msg_len = size + 1; + + crc = anx7625_checksum((u8 *)msg, size + HEADER_LEN); + msg->buf[size] = 0 - crc; + + ret = anx7625_wait_msg_empty(ctx); + if (ret) + return ret; + + ret = anx7625_reg_block_write(ctx, ctx->i2c.rx_p0_client, + CMD_SEND_BUF + 1, size + HEADER_LEN, + &msg->msg_type); + ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client, CMD_SEND_BUF, + msg->msg_len); + return ret; +} + +static int anx7625_typec_dr_set(struct typec_port *port, enum typec_data_role role) +{ + struct anx7625_data *ctx = typec_get_drvdata(port); + + if (role == ctx->typec_data_role) + return 0; + + return anx7625_send_msg(ctx, 0x11, NULL, 0); +} + +static const struct typec_operations anx7625_typec_ops = { + .dr_set = anx7625_typec_dr_set, +}; + static void anx7625_typec_set_orientation(struct anx7625_data *ctx) { u32 val = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); @@ -1542,6 +1609,7 @@ static int anx7625_typec_register(struct anx7625_data *ctx) typec_cap.orientation_aware = true; typec_cap.driver_data = ctx; + typec_cap.ops = &anx7625_typec_ops; ctx->typec_port = typec_register_port(ctx->dev, &typec_cap); if (IS_ERR(ctx->typec_port)) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h index a18561c213af9..957d234ec07c8 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.h +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h @@ -67,6 +67,9 @@ #define CC2_RA BIT(5) #define CC2_RP (BIT(6) | BIT(7)) +#define CMD_SEND_BUF 0xC0 +#define CMD_RECV_BUF 0xE0 + /******** END of I2C Address 0x58 ********/ /***************************************************************/ @@ -462,6 +465,14 @@ struct anx7625_i2c_client { struct typec_port; struct usb_role_switch; +#define MAX_BUF_LEN 30 +struct fw_msg { + u8 msg_len; + u8 msg_type; + u8 buf[MAX_BUF_LEN]; +} __packed; +#define HEADER_LEN 2 + struct anx7625_data { struct anx7625_platform_data pdata; struct platform_device *audio_pdev; @@ -497,6 +508,7 @@ struct anx7625_data { struct drm_connector *connector; struct mipi_dsi_device *dsi; struct drm_dp_aux aux; + struct fw_msg send_msg; }; #endif /* __ANX7625_H__ */ From b65bef47f976377f89a951ace6f17caba988058c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 4 Mar 2026 09:35:52 +0100 Subject: [PATCH 22/29] UPSTREAM: drm: bridge: anx7625: enforce CONFIG_USB_ROLE_SWITCH dependency When CONFIG_TYPEC is enabled, but USB_ROLE_SWITCH=m, the anx7625 driver fails to link as built-in: aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/anx7625.o: in function `anx7625_i2c_remove': anx7625.c:(.text+0x6ec): undefined reference to `usb_role_switch_put' aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/anx7625.o: in function `anx7625_typec_set_status': anx7625.c:(.text+0x3080): undefined reference to `usb_role_switch_set_role' aarch64-linux-ld: drivers/gpu/drm/bridge/analogix/anx7625.o: in function `anx7625_i2c_probe': anx7625.c:(.text+0x5368): undefined reference to `fwnode_usb_role_switch_get' The problem is that both dependencies are optional in the sense of allowing the anx7625 driver to call the exported interfaces to be used from a loadable module, but cannot work for built-in drivers. It would be possible to handle all nine combinations of the CONFIG_TYPEC and CONFIG_USB_ROLE_SWITCH tristate options, but that does add a lot of complexity that seems unnecessary when in reality any user of this driver would have both enabled anyway. Turn both dependencies into hard 'depends on' here to only allow configurations where it's possible to actually use them, and remove the misguided IS_REACHABLE() check that did nothing here. Fixes: f81455b2d332 ("drm: bridge: anx7625: implement minimal Type-C support") Signed-off-by: Arnd Bergmann Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260304083604.724519-1-arnd@kernel.org Signed-off-by: Dmitry Baryshkov (cherry picked from commit 10e9ff46fe07bdfa8c11434d4b943f89d8ba74f6) Signed-off-by: Ricardo Salveti --- drivers/gpu/drm/bridge/analogix/Kconfig | 3 ++- drivers/gpu/drm/bridge/analogix/anx7625.c | 17 ----------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index f3448b0631fea..03dc7ffe824a9 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -34,7 +34,8 @@ config DRM_ANALOGIX_ANX7625 tristate "Analogix Anx7625 MIPI to DP interface support" depends on DRM depends on OF - depends on TYPEC || !TYPEC + depends on TYPEC + depends on USB_ROLE_SWITCH select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 9410283b84a57..0b842805e0e4b 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1483,7 +1483,6 @@ static void anx7625_start_dp_work(struct anx7625_data *ctx) DRM_DEV_DEBUG_DRIVER(dev, "Secure OCM version=%02x\n", ret); } -#if IS_REACHABLE(CONFIG_TYPEC) static u8 anx7625_checksum(u8 *buf, u8 len) { u8 ret = 0; @@ -1635,22 +1634,6 @@ static void anx7625_typec_unregister(struct anx7625_data *ctx) usb_role_switch_put(ctx->role_sw); typec_unregister_port(ctx->typec_port); } -#else -static void anx7625_typec_set_status(struct anx7625_data *ctx, - unsigned int intr_status, - unsigned int intr_vector) -{ -} - -static int anx7625_typec_register(struct anx7625_data *ctx) -{ - return 0; -} - -static void anx7625_typec_unregister(struct anx7625_data *ctx) -{ -} -#endif static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx) { From 7038a78f606bc2e665584cba070ac72441f1ebf8 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Sun, 15 Feb 2026 03:30:02 +0200 Subject: [PATCH 23/29] UPSTREAM: drm: bridge: anx7625: don't crash if Type-C port is not used The typec_set_*() functions do not tolerate being passed the NULL typec_port instance. However, if CONFIG_TYPEC is enabled, but anx7625 DT node doesn't have the usb-c connector fwnode, then typec_port remains NULL, crashing the kernel. Prevent calling typec_set_foo() functions by checking that ctx->typec_port is not NULL in anx7625_typec_set_status(). Call trace: typec_set_orientation+0x18/0x68 (P) anx7625_typec_set_status+0x108/0x13c anx7625_work_func+0x124/0x438 process_one_work+0x214/0x648 worker_thread+0x1b4/0x358 kthread+0x14c/0x214 ret_from_fork+0x10/0x20 Code: 910003fd a90153f3 aa0003f3 2a0103f4 (f9431400) Fixes: f81455b2d332 ("drm: bridge: anx7625: implement minimal Type-C support") Reported-by: Salendarsingh Gaud Signed-off-by: Loic Poulain [db: dropped chunk anx7625_typec_unregister(), wrote commit message] Cc: Amit Kucheria Reviewed-by: Neil Armstrong Link: https://patch.msgid.link/20260215-anx-fix-no-typec-v1-1-75172a5ca88b@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov (cherry picked from commit 8e3d8b33859bb8229d1f0b88752cbecb4932790a) Signed-off-by: Ricardo Salveti --- drivers/gpu/drm/bridge/analogix/anx7625.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 0b842805e0e4b..1e4c1c013581e 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1566,6 +1566,9 @@ static void anx7625_typec_set_status(struct anx7625_data *ctx, unsigned int intr_status, unsigned int intr_vector) { + if (!ctx->typec_port) + return; + if (intr_vector & CC_STATUS) anx7625_typec_set_orientation(ctx); if (intr_vector & DATA_ROLE_STATUS) { From b49d44c99e0a1e5365dfe49a5fcf9a7bc93885ec Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 11 Feb 2026 11:17:27 +0200 Subject: [PATCH 24/29] UPSTREAM: drm: bridge: anx7625: correctly detect if PD can be disabled During initial checks the ANX7625 bridge can be powered on before setting up the Type-C port. At this point, when anx7625_ocm_loading_check() checks if it can disable PD or not, it will notice that typec_port is not set and disable PD, breaking orientation and HPD handling. Unify the check between anx7625_ocm_loading_check() anx7625_i2c_probe() and anx7625_typec_register() and check for the presence of the "connector" node. Fixes: 8ad0f7d2e6fd ("drm: bridge: anx7625: implement message sending") Reviewed-by: Neil Armstrong Reviewed-by: Xin Ji Tested-by: Loic Poulain Link: https://patch.msgid.link/20260211-anx7625-fix-pd-v1-1-1dd31451b06f@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov (cherry picked from commit 91d045058c68ab0ae133cd0bd8ed25a32c3dee97) Signed-off-by: Ricardo Salveti --- drivers/gpu/drm/bridge/analogix/anx7625.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 1e4c1c013581e..513c11cdbc74a 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1363,6 +1363,18 @@ static void anx7625_configure_hpd(struct anx7625_data *ctx) anx7625_hpd_timer_config(ctx); } +static bool anx7625_need_pd(struct anx7625_data *ctx) +{ + struct fwnode_handle *fwnode; + + fwnode = device_get_named_child_node(ctx->dev, "connector"); + if (!fwnode) + return false; + + fwnode_handle_put(fwnode); + return true; +} + static int anx7625_ocm_loading_check(struct anx7625_data *ctx) { int ret; @@ -1378,7 +1390,7 @@ static int anx7625_ocm_loading_check(struct anx7625_data *ctx) if ((ret & FLASH_LOAD_STA_CHK) != FLASH_LOAD_STA_CHK) return -ENODEV; - if (!ctx->typec_port) + if (!anx7625_need_pd(ctx)) anx7625_disable_pd_protocol(ctx); anx7625_configure_hpd(ctx); @@ -2910,12 +2922,7 @@ static int anx7625_i2c_probe(struct i2c_client *client) } if (!platform->pdata.low_power_mode) { - struct fwnode_handle *fwnode; - - fwnode = device_get_named_child_node(dev, "connector"); - if (fwnode) - fwnode_handle_put(fwnode); - else + if (!anx7625_need_pd(platform)) anx7625_disable_pd_protocol(platform); anx7625_configure_hpd(platform); From a124e18aac3a1436e1021942fb413af8fc9aa705 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 13 Feb 2026 19:25:25 +0200 Subject: [PATCH 25/29] UPSTREAM: arm64: dts: qcom: qrb2210-arduino-imola: describe DSI / DP bridge Aruino Uno-Q uses Analogix ANX7625 DSI-to-DP bridge to convert DSI signals to the connected USB-C DisplayPort dongles. Decribe the chip, USB-C connector and routing of USB and display signals. Co-developed-by: Martino Facchin Signed-off-by: Martino Facchin Tested-by: Loic Poulain Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260213-uno-q-anx7625-v2-1-c23359616528@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit d5574bb935e38c208bb7a20acaa4233b935f1ef9) Signed-off-by: Ricardo Salveti --- .../boot/dts/qcom/qrb2210-arduino-imola.dts | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts index 2e9f26ed2f39f..713300bc3d556 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "qcm2290.dtsi" #include "pm4125.dtsi" @@ -109,6 +110,15 @@ leds = <&ledr>, <&ledg>, <&ledb>; }; + vreg_anx_30: regulator-anx-30 { + compatible = "regulator-fixed"; + regulator-name = "anx30"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + }; + /* PM4125 charger out, supplied by VBAT */ vph_pwr: regulator-vph-pwr { compatible = "regulator-fixed"; @@ -142,6 +152,86 @@ clock-frequency = <100000>; status = "okay"; + + anx7625: encoder@58 { + compatible = "analogix,anx7625"; + reg = <0x58>; + interrupts-extended = <&tlmm 81 IRQ_TYPE_EDGE_FALLING>; + vdd10-supply = <&pm4125_l11>; + vdd18-supply = <&pm4125_l15>; + vdd33-supply = <&vreg_anx_30>; + analogix,audio-enable; + analogix,lane0-swing = /bits/ 8 <0x14 0x54 0x64 0x74>; + analogix,lane1-swing = /bits/ 8 <0x14 0x54 0x64 0x74>; + + pinctrl-0 = <&anx7625_int_pin>, <&anx7625_cable_det_pin>; + + connector { + compatible = "usb-c-connector"; + power-role = "sink"; + data-role = "dual"; + try-power-role = "sink"; + + pd-revision = /bits/ 8 <0x03 0x00 0x00 0x00>; + op-sink-microwatt = <15000000>; + sink-pdos = ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + anx_hs_in: endpoint { + remote-endpoint = <&usb_dwc3_hs>; + }; + }; + + port@1 { + reg = <1>; + + anx_ss_in: endpoint { + remote-endpoint = <&usb_qmpphy_out>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + anx_dsi0_in: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + data-lanes = <0 1 2 3>; + }; + }; + }; + }; +}; + +&mdss { + status = "okay"; +}; + +&mdss_dsi0 { + vdda-supply = <&pm4125_l5>; + + status = "okay"; +}; + +&mdss_dsi0_out { + remote-endpoint = <&anx_dsi0_in>; + data-lanes = <0 1 2 3>; +}; + +&mdss_dsi0_phy { + status = "okay"; }; &pm4125_vbus { @@ -353,6 +443,22 @@ output-disable; }; + anx7625_cable_det_pin: anx7625-cable-det-pins-state { + pins = "gpio46"; + function = "gpio"; + drive-strength = <16>; + output-disable; + bias-pull-up; + }; + + anx7625_int_pin: anx7625-int-pins-state { + pins = "gpio81"; + function = "gpio"; + drive-strength = <16>; + output-disable; + bias-pull-up; + }; + key_volp_n: key-volp-n-state { pins = "gpio96"; function = "gpio"; @@ -420,6 +526,10 @@ status = "okay"; }; +&usb_dwc3_hs { + remote-endpoint = <&anx_hs_in>; +}; + &usb_hsphy { vdd-supply = <&pm4125_l12>; vdda-pll-supply = <&pm4125_l13>; @@ -435,6 +545,10 @@ status = "okay"; }; +&usb_qmpphy_out { + remote-endpoint = <&anx_ss_in>; +}; + &wifi { vdd-0.8-cx-mx-supply = <&pm4125_l7>; vdd-1.8-xo-supply = <&pm4125_l13>; From a5bff1276295cd80507e2179707e3275a735ecdc Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 6 Jul 2026 18:01:08 +0530 Subject: [PATCH 26/29] FROMGIT: arm64: dts: qcom: Fix pm4125 vbus regulator compatible and constraints Remove pm8150b fallback compatible from pm4125_vbus and fix regulator constraints in qrb2210 DTS files to use microvolt instead of microamp. Signed-off-by: Rakesh Kota Reviewed-by: Bryan O'Donoghue Reviewed-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260706-add_pm4125-vbus-reg-v3-4-999d78a87b81@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit cab6d9627ef4bb72c5d6ec3f216028e4271b9abe) Signed-off-by: Ricardo Salveti --- arch/arm64/boot/dts/qcom/pm4125.dtsi | 2 +- arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts | 4 ++-- arch/arm64/boot/dts/qcom/qrb2210-rb1.dts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/pm4125.dtsi b/arch/arm64/boot/dts/qcom/pm4125.dtsi index ad410b8c4f6be..ca900948c0b3e 100644 --- a/arch/arm64/boot/dts/qcom/pm4125.dtsi +++ b/arch/arm64/boot/dts/qcom/pm4125.dtsi @@ -37,7 +37,7 @@ }; pm4125_vbus: usb-vbus-regulator@1100 { - compatible = "qcom,pm4125-vbus-reg", "qcom,pm8150b-vbus-reg"; + compatible = "qcom,pm4125-vbus-reg"; reg = <0x1100>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts index 713300bc3d556..9f21fd1f677cf 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-arduino-imola.dts @@ -235,8 +235,8 @@ }; &pm4125_vbus { - regulator-min-microamp = <500000>; - regulator-max-microamp = <500000>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts index 3eedfb2cf4799..8c5f9c79b86a7 100644 --- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts +++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts @@ -318,8 +318,8 @@ }; &pm4125_vbus { - regulator-min-microamp = <500000>; - regulator-max-microamp = <500000>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; status = "okay"; }; From fc6f3e380a6c4bd5f009d4b08cdc7f3cabb4d654 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 22 Jul 2026 15:46:08 +0300 Subject: [PATCH 27/29] FROMGIT: clk: qcom: gcc-qcm2290: don't park QUP RCGs upon registration The gcc_qupv3_wrap0_s[0-5]_clk_src RCGs feed the QUP serial engines (UART/I2C/SPI). Since shared RCGs are parked to XO at registration time, binding the gcc-qcm2290 driver reprograms these clocks away from the rate configured by the bootloader. For the UART used as the boot console this drops early console output until the serial driver later reconfigures the clock. Switch the QUP wrap0 clock sources over to clk_rcg2_shared_no_init_park_ops so their frequency is left unchanged at registration time, keeping the bootloader-configured console working across the gcc driver probe. Fixes: 01a0a6cc8cfd ("clk: qcom: Park shared RCGs upon registration") Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260722-agatti-no-park-v1-1-31ae3a4774e5@oss.qualcomm.com Signed-off-by: Bjorn Andersson (cherry picked from commit 9c4cee964e0ccc155e4ab8fa6cec88fffc262c63) Signed-off-by: Ricardo Salveti --- drivers/clk/qcom/gcc-qcm2290.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/qcom/gcc-qcm2290.c b/drivers/clk/qcom/gcc-qcm2290.c index 1c832f1053be9..abef4ad0a8567 100644 --- a/drivers/clk/qcom/gcc-qcm2290.c +++ b/drivers/clk/qcom/gcc-qcm2290.c @@ -1082,7 +1082,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { .name = "gcc_qupv3_wrap0_s0_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { @@ -1098,7 +1098,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { .name = "gcc_qupv3_wrap0_s1_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { @@ -1114,7 +1114,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { .name = "gcc_qupv3_wrap0_s2_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { @@ -1130,7 +1130,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { .name = "gcc_qupv3_wrap0_s3_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { @@ -1146,7 +1146,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { .name = "gcc_qupv3_wrap0_s4_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { @@ -1162,7 +1162,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { .name = "gcc_qupv3_wrap0_s5_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, }; static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { From e12e5dc44b2c838a5848ad2724a177055d50edaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sebastian=20G=C3=B6tte?= Date: Wed, 29 Jul 2026 19:41:05 +0200 Subject: [PATCH 28/29] UPSTREAM: serial: qcom-geni: fix TX DMA buffer flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When transmit flushing a qcom-geni UART during an ongoing TX DMA, the UART gets stuck infinitely repeating corrupted TX DMA frames. The DMA-mode uart_ops does not provide a flush_buffer callback, so an in-flight transfer can complete after serial core has reset the transmit kfifo, underflowing its length and resubmitting page-sized transfers indefinitely. Add one that stops the transfer and clears tx_remaining and tx_queued. The stop path was also broken: it unmapped the buffer while the serial engine could still read it, and never reset the TX DMA state machine. Cancel the main sequencer command first, then reset the state machine and wait for it before unmapping. Drop the early return so a pending mapping is also cleaned up when the main command is inactive. The bug can be triggered from userspace with a large write immediately followed by TCOFLUSH. A following tcdrain will hang forever. The bug was reproduced and this fix was validated on Arduino Uno Q (QRB2210) using /dev/ttyHS1. Assisted-by: Claude:claude-5-opus Codex:gpt-5 Signed-off-by: Jan Sebastian Götte Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA") Cc: stable Reviewed-by: Praveen Talari Link: https://patch.msgid.link/20260729174105.21838-2-git@jaseg.de Signed-off-by: Greg Kroah-Hartman (cherry picked from commit e3c04834ae1ab5e9cfbe8ac54ec734aa4774249d) Signed-off-by: Ricardo Salveti --- drivers/tty/serial/qcom_geni_serial.c | 43 ++++++++++++++------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index a34817a4428c9..1d561a00cbbd9 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -149,6 +149,7 @@ static const struct uart_ops qcom_geni_uart_pops; static struct uart_driver qcom_geni_console_driver; static struct uart_driver qcom_geni_uart_driver; +static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport); static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport); static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport); static int qcom_geni_serial_port_setup(struct uart_port *uport); @@ -627,35 +628,34 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *uport) return !readl(uport->membase + SE_GENI_TX_FIFO_STATUS); } +static void qcom_geni_serial_flush_buffer_dma(struct uart_port *uport) +{ + struct qcom_geni_serial_port *port = to_dev_port(uport); + + qcom_geni_serial_stop_tx_dma(uport); + port->tx_remaining = 0; + port->tx_queued = 0; +} + static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport) { struct qcom_geni_serial_port *port = to_dev_port(uport); - bool done; - if (!qcom_geni_serial_main_active(uport)) - return; + if (qcom_geni_serial_main_active(uport)) + __qcom_geni_serial_cancel_tx_cmd(uport); if (port->tx_dma_addr) { + writel(1, uport->membase + SE_DMA_TX_FSM_RST); + if (!qcom_geni_serial_poll_bit(uport, SE_DMA_TX_IRQ_STAT, + TX_RESET_DONE, true)) + dev_err_ratelimited(uport->dev, "TX DMA reset failed"); + writel(TX_RESET_DONE | TX_DMA_DONE, + uport->membase + SE_DMA_TX_IRQ_CLR); + geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining); port->tx_dma_addr = 0; - port->tx_remaining = 0; } - - geni_se_cancel_m_cmd(&port->se); - - done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, - M_CMD_CANCEL_EN, true); - if (!done) { - geni_se_abort_m_cmd(&port->se); - done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, - M_CMD_ABORT_EN, true); - if (!done) - dev_err_ratelimited(uport->dev, "M_CMD_ABORT_EN not set"); - writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); - } - - writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); } static void qcom_geni_serial_start_tx_dma(struct uart_port *uport) @@ -1171,7 +1171,7 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport) uart_port_unlock_irq(uport); } -static void qcom_geni_serial_flush_buffer(struct uart_port *uport) +static void qcom_geni_serial_flush_buffer_fifo(struct uart_port *uport) { qcom_geni_serial_cancel_tx_cmd(uport); } @@ -1695,7 +1695,7 @@ static const struct uart_ops qcom_geni_console_pops = { .request_port = qcom_geni_serial_request_port, .config_port = qcom_geni_serial_config_port, .shutdown = qcom_geni_serial_shutdown, - .flush_buffer = qcom_geni_serial_flush_buffer, + .flush_buffer = qcom_geni_serial_flush_buffer_fifo, .type = qcom_geni_serial_get_type, .set_mctrl = qcom_geni_serial_set_mctrl, .get_mctrl = qcom_geni_serial_get_mctrl, @@ -1718,6 +1718,7 @@ static const struct uart_ops qcom_geni_uart_pops = { .request_port = qcom_geni_serial_request_port, .config_port = qcom_geni_serial_config_port, .shutdown = qcom_geni_serial_shutdown, + .flush_buffer = qcom_geni_serial_flush_buffer_dma, .type = qcom_geni_serial_get_type, .set_mctrl = qcom_geni_serial_set_mctrl, .get_mctrl = qcom_geni_serial_get_mctrl, From 8956c52cd083e3bd3241a3aead9c811424654602 Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Wed, 8 Jul 2026 21:17:26 +0800 Subject: [PATCH 29/29] FROMGIT: serial: qcom-geni: do not advance stale DMA completions The qcom GENI serial DMA TX completion path advances the transmit fifo by the number of bytes recorded in port->tx_remaining. If uart_flush_buffer() runs after the hardware has completed a DMA transfer but before the DMA completion interrupt has been handled, the serial core resets the transmit fifo while port->tx_remaining still describes the old DMA transfer. A previous fix avoided advancing an empty fifo by checking that the fifo length is at least tx_remaining. That still does not distinguish the old DMA payload from new bytes written after the flush. If userspace writes new data before the stale DMA completion interrupt is handled, the fifo can again contain at least tx_remaining bytes and the stale completion can advance and discard those new bytes. Mark an in-flight DMA transfer stale when the transmit fifo is flushed. The later completion still unprepares the original DMA mapping using the saved length, but it no longer advances the transmit fifo. Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA") Signed-off-by: Guangshuo Li Link: https://patch.msgid.link/20260708131726.768692-1-lgs201920130244@gmail.com Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 7ea38c49e7178960926657863299face6dc0e1b0) Signed-off-by: Ricardo Salveti --- drivers/tty/serial/qcom_geni_serial.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 1d561a00cbbd9..953b737357103 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -136,6 +136,7 @@ struct qcom_geni_serial_port { unsigned int tx_remaining; unsigned int tx_queued; + bool tx_dma_stale; int wakeup_irq; bool rx_tx_swap; bool cts_rts_swap; @@ -688,6 +689,7 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport) } port->tx_remaining = xmit_size; + port->tx_dma_stale = false; } static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport) @@ -1020,6 +1022,7 @@ static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport) struct qcom_geni_serial_port *port = to_dev_port(uport); struct tty_port *tport = &uport->state->port; unsigned int fifo_len = kfifo_len(&tport->xmit_fifo); + bool tx_dma_stale = port->tx_dma_stale; /* * Only advance the kfifo if it still contains the bytes that were @@ -1030,12 +1033,13 @@ static void qcom_geni_serial_handle_tx_dma(struct uart_port *uport) * kfifo->in, making kfifo_len() wrap to UART_XMIT_SIZE - tx_remaining * and triggering a spurious large DMA transfer of stale data. */ - if (fifo_len >= port->tx_remaining) + if (!tx_dma_stale && fifo_len >= port->tx_remaining) uart_xmit_advance(uport, port->tx_remaining); geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining); port->tx_dma_addr = 0; port->tx_remaining = 0; + port->tx_dma_stale = false; if (!kfifo_is_empty(&tport->xmit_fifo)) qcom_geni_serial_start_tx_dma(uport); @@ -1173,6 +1177,10 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport) static void qcom_geni_serial_flush_buffer_fifo(struct uart_port *uport) { + struct qcom_geni_serial_port *port = to_dev_port(uport); + + if (port->tx_dma_addr) + port->tx_dma_stale = true; qcom_geni_serial_cancel_tx_cmd(uport); }