Devicetree
 help / color / mirror / Atom feed
* [PATCH v4 2/7] PCI: intel-gw: Remove unused define
From: Florian Eckert @ 2026-04-15  8:01 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Krzysztof Wilczyński,
	Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Johan Hovold,
	Sajid Dalvi, Ajay Agarwal, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-pci, linux-kernel, devicetree, Florian Eckert,
	Eckert.Florian, ms
In-Reply-To: <20260415-pcie-intel-gw-v4-0-ad45d2418c8e@dev.tdt.de>

The C preprocessor define 'PCIE_APP_INTX_OFST' is not used in the sources
and can therefore be deleted.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
 drivers/pci/controller/dwc/pcie-intel-gw.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c
index c21906eced61896c8a8307dbd6b72d229f9a5c5f..80d1607c46cbbb1e274b37a0bb9377a877678f5d 100644
--- a/drivers/pci/controller/dwc/pcie-intel-gw.c
+++ b/drivers/pci/controller/dwc/pcie-intel-gw.c
@@ -47,7 +47,6 @@
 #define PCIE_APP_IRN_INTD		BIT(16)
 #define PCIE_APP_IRN_MSG_LTR		BIT(18)
 #define PCIE_APP_IRN_SYS_ERR_RC		BIT(29)
-#define PCIE_APP_INTX_OFST		12
 
 #define PCIE_APP_IRN_INT \
 	(PCIE_APP_IRN_AER_REPORT | PCIE_APP_IRN_PME | \

-- 
2.47.3


^ permalink raw reply related

* [PATCH v4 1/7] MAINTAINERS: Remove bouncing intel-gw maintainer
From: Florian Eckert @ 2026-04-15  8:01 UTC (permalink / raw)
  To: Lorenzo Pieralisi, Krzysztof Wilczyński,
	Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Johan Hovold,
	Sajid Dalvi, Ajay Agarwal, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-pci, linux-kernel, devicetree, Florian Eckert,
	Eckert.Florian, ms
In-Reply-To: <20260415-pcie-intel-gw-v4-0-ad45d2418c8e@dev.tdt.de>

The maintainer's email address has been bouncing for months. Mark the PCI
intel-gw driver as orphaned.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
 MAINTAINERS | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index d1cc0e12fe1f004da89b1aa339116908f642e894..725f333f265bef416b5144c56649cb6eae736e40 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20518,9 +20518,8 @@ F:	Documentation/devicetree/bindings/pci/intel,keembay-pcie*
 F:	drivers/pci/controller/dwc/pcie-keembay.c
 
 PCIE DRIVER FOR INTEL LGM GW SOC
-M:	Chuanhua Lei <lchuanhua@maxlinear.com>
 L:	linux-pci@vger.kernel.org
-S:	Maintained
+S:	Orphan
 F:	Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
 F:	drivers/pci/controller/dwc/pcie-intel-gw.c
 

-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH 4/5] media: dt-bindings: add NXP i.MX95 compatible string
From: Krzysztof Kozlowski @ 2026-04-15  8:10 UTC (permalink / raw)
  To: Guoniu Zhou
  Cc: Michael Riesch, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Laurent Pinchart, Frank Li, linux-media, linux-kernel, devicetree,
	imx, linux-arm-kernel, linux-rockchip
In-Reply-To: <20260415-csi2_imx95-v1-4-7d63f3508719@oss.nxp.com>

On Wed, Apr 15, 2026 at 11:46:55AM +0800, Guoniu Zhou wrote:
> The i.MX95 CSI-2 controller is nearly identical to i.MX93, with the
> only difference being the use of IDI (Image Data Interface) instead
> of IPI (Image Pixel Interface). The binding constraints are otherwise
> the same.

Nearly identical with some difference really, really suggests they are
compatible. Express compatibility or explain why they are not compatible
(difference between IDI and IPI unfortunately does not help me).

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/4] dt-bindings: clock: marvell,pxa1908: Add #reset-cells
From: Krzysztof Kozlowski @ 2026-04-15  8:08 UTC (permalink / raw)
  To: Duje Mihanović
  Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Karel Balej, linux-arm-kernel, linux-clk,
	devicetree, linux-kernel, phone-devel, ~postmarketos/upstreaming,
	Duje Mihanović
In-Reply-To: <20260414-pxa1908-clk-reset-v1-1-94bae5f3a8cf@dujemihanovic.xyz>

On Tue, Apr 14, 2026 at 09:51:50PM +0200, Duje Mihanović wrote:
> From: Duje Mihanović <duje@dujemihanovic.xyz>
> 
> The APBC and APBCP controllers have reset lines exposed. Give them
> a #reset-cells so that they may be used as reset controllers.
> 
> Signed-off-by: Duje Mihanović <duje@dujemihanovic.xyz>
> ---
>  .../devicetree/bindings/clock/marvell,pxa1908.yaml | 34 +++++++++++++++-------
>  1 file changed, 24 insertions(+), 10 deletions(-)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: qcom: Document panasonic,eluga-u2
From: Krzysztof Kozlowski @ 2026-04-15  8:07 UTC (permalink / raw)
  To: Lin, Meng-Bo
  Cc: linux-kernel, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, devicetree,
	phone-devel, ~postmarketos/upstreaming
In-Reply-To: <20260414184429.168612-2-linmengbo06890@proton.me>

On Tue, Apr 14, 2026 at 06:44:48PM +0000, Lin, Meng-Bo wrote:
> Document the new panasonic,eluga-u2 device tree bindings used in
> msm8916-panasonic-eluga-u2.
> 
> Signed-off-by: "Lin, Meng-Bo" <linmengbo06890@proton.me>
> ---
>  Documentation/devicetree/bindings/arm/qcom.yaml | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: remoteproc: add AMD MicroBlaze binding
From: Michal Simek @ 2026-04-15  8:06 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Ben Levinsky, andersson, mathieu.poirier
  Cc: robh, krzk+dt, conor+dt, linux-remoteproc, devicetree,
	linux-kernel, tanmay.shah
In-Reply-To: <9cd3686a-5fa6-49cc-9b38-96637b9fca39@kernel.org>



On 4/15/26 09:07, Krzysztof Kozlowski wrote:
> On 15/04/2026 08:55, Michal Simek wrote:
>>>>
>>>> Does it make sense?
>>>
>>> Yes, drop from DT. No need for generic stuff. Or describe the hardware.
>>
>> You need to describe that connection to HW. GPIOs, memory location, etc.
>> It means there must be any description.
> 
> No, you can write user-space driver or pass everything through SW nodes.
> No need for DT description.

The firmware memory typically sits behind AXI-to-AXI bridges and 

interconnect switches. The bus topology varies between FPGA designs. 

DT ranges-based address translation is the standard way to describe 

this, and pushing it into userspace would just mean hardcoding what 

ranges already provides.

I don't think SW nodes should be used here.

> 
> But if you want a DT description, then it must be for the specific
> hardware, since the hardware is not generic.

But there is specific HW loaded. It is loaded at power up and don't change over 
life cycle. What I am just saying that access to this fixed HW (in fpga) is 
generic. At this stage memory and gpio only.

What I was trying to say is that the hardware topology (memory window + 

reset GPIO) is the same regardless of the soft-core cpu (MicroBlaze,
RISC-V, etc.)/fpga, so naming it after the ISA architecture felt wrong to me 

too.

When I look at other bindings. For example this one.
Documentation/devicetree/bindings/remoteproc/qcom,glink-rpm-edge.yaml

the compatible describes the communication mechanism (FIFO-based G-Link), not 
the specific processor behind it. 

  

Our case is similar the compatible describes the control mechanism firmware 
loaded through a memory window, processor started via GPIO reset. What sits 
behind that interface varies and is opaque to the binding.
  

Would something like "amd,mem-gpio-rproc" be acceptable, following the same 
pattern where the compatible identifies the interface mechanism?

Thanks,
Michal


^ permalink raw reply

* Re: [PATCH 1/3] regulator: dt-bindings: mt6360: add buck regulator supplies
From: Krzysztof Kozlowski @ 2026-04-15  8:06 UTC (permalink / raw)
  To: Louis-Alexis Eyraud
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Liam Girdwood, Mark Brown, Gene Chen,
	kernel, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260414-mtk-g1200-pmic-cleanup-v1-1-2a7193ed4e93@collabora.com>

On Tue, Apr 14, 2026 at 01:44:10PM +0200, Louis-Alexis Eyraud wrote:
> MT6360 PMIC provides 2 buck and 6 ldo regulators, that have each one a
> separate supply.
> Currently, the supplies for the ldo regulators are described in the
> dt-bindings but the ones for the buck regulators are not.
> 
> Add the descriptions for these missing supplies.
> 
> Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
> ---
>  Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml | 4 ++++
>  1 file changed, 4 insertions(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH] arm64: dts: qcom: monaco: add GDSP fastrpc-compute-cb nodes
From: Konrad Dybcio @ 2026-04-15  8:05 UTC (permalink / raw)
  To: ekansh.gupta, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, quic_bkumar, quic_chennak,
	srinivas.kandagatla
  Cc: linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260415-monacogdsp-v1-1-077ded36c7fc@oss.qualcomm.com>

On 4/15/26 8:40 AM, Ekansh Gupta via B4 Relay wrote:
> From: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> 
> Add GDSP fastrpc compute-cb nodes for monaco SoC.
> 
> Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Konrad

^ permalink raw reply

* Re: [PATCH v7 5/6] arm64: dts: rockchip: refactor items from Orange Pi 5/b to prep for Pro
From: Alexey Charkov @ 2026-04-15  8:02 UTC (permalink / raw)
  To: Dennis Gilmore
  Cc: Andrew Lunn, Andrzej Hajda, Chaoyi Chen, Conor Dooley,
	David Airlie, devicetree, dri-devel, FUKAUMI Naoki,
	Heiko Stuebner, Hsun Lai, Jernej Skrabec, Jimmy Hon, John Clark,
	Jonas Karlman, Krzysztof Kozlowski, Laurent Pinchart,
	linux-arm-kernel, linux-kernel, linux-rockchip, Maarten Lankhorst,
	Maxime Ripard, Michael Opdenacker, Michael Riesch, Mykola Kvach,
	Neil Armstrong, Peter Robinson, Quentin Schulz, Robert Foss,
	Rob Herring, Simona Vetter, Thomas Zimmermann
In-Reply-To: <20260414214104.1363987-6-dennis@ausil.us>

On Wed, Apr 15, 2026 at 1:41 AM Dennis Gilmore <dennis@ausil.us> wrote:
>
> The Orange Pi 5 Pro uses the same SoC and base as the Orange Pi 5 and
> Orange Pi 5B but has had sound, USB, and leds wired up differently. The
> 5 and 5B boards use gmac for ethernet where the Pro has a PCIe attached
> NIC.
>
> Move the 5/5B-specific bits (analog-sound/es8388, FUSB302 Type-C,
> gmac1, pwm-leds, i2s1_8ch routing, USB role-switch plumbing) out of
> rk3588s-orangepi-5.dtsi into a new rk3588s-orangepi-5-5b.dtsi that is
> included by both 5 and 5B.
>
> The RK806 PLDO1 and PLDO2 outputs are wired differently between the
> 5/5B and the Pro (PLDO1/PLDO2 are swapped), so label the PMIC node
> rk806_single in the base dtsi, drop pldo-reg1/pldo-reg2 from it, and
> define them via a &rk806_single regulators augmentation in
> rk3588s-orangepi-5-5b.dtsi. The Pro will supply its own mapping.
>
> Signed-off-by: Dennis Gilmore <dennis@ausil.us>
> ---
>  .../dts/rockchip/rk3588s-orangepi-5-5b.dtsi   | 222 +++++++++++++++++
>  .../boot/dts/rockchip/rk3588s-orangepi-5.dts  |   6 +-
>  .../boot/dts/rockchip/rk3588s-orangepi-5.dtsi | 225 +-----------------
>  .../boot/dts/rockchip/rk3588s-orangepi-5b.dts |   2 +-
>  4 files changed, 240 insertions(+), 215 deletions(-)
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi

Hi Dennis,

Sashiko makes a good point [1] about also moving the vbus_typec to the
*-5-5b.dtsi, given that it's not used on the Pro. Same with mdio1
which only makes sense together with its respective GMAC. Other than
that, this looks good to me - feel free to include:

Reviewed-by: Alexey Charkov <alchark@gmail.com

Best regards,
Alexey

[1] https://sashiko.dev/#/patchset/20260414214104.1363987-1-dennis%40ausil.us

> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi
> new file mode 100644
> index 000000000000..9e987ffa6241
> --- /dev/null
> +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi
> @@ -0,0 +1,222 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Device tree definitions shared by the Orange Pi 5 and Orange Pi 5B
> + * but not the Orange Pi 5 Pro.
> + */
> +
> +#include <dt-bindings/usb/pd.h>
> +#include "rk3588s-orangepi-5.dtsi"
> +
> +/ {
> +       aliases {
> +               ethernet0 = &gmac1;
> +       };
> +
> +       analog-sound {
> +               compatible = "simple-audio-card";
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&hp_detect>;
> +               simple-audio-card,name = "rockchip,es8388";
> +               simple-audio-card,bitclock-master = <&masterdai>;
> +               simple-audio-card,format = "i2s";
> +               simple-audio-card,frame-master = <&masterdai>;
> +               simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
> +               simple-audio-card,mclk-fs = <256>;
> +               simple-audio-card,routing =
> +                       "Headphones", "LOUT1",
> +                       "Headphones", "ROUT1",
> +                       "LINPUT1", "Microphone Jack",
> +                       "RINPUT1", "Microphone Jack",
> +                       "LINPUT2", "Onboard Microphone",
> +                       "RINPUT2", "Onboard Microphone";
> +               simple-audio-card,widgets =
> +                       "Microphone", "Microphone Jack",
> +                       "Microphone", "Onboard Microphone",
> +                       "Headphone", "Headphones";
> +
> +               simple-audio-card,cpu {
> +                       sound-dai = <&i2s1_8ch>;
> +               };
> +
> +               masterdai: simple-audio-card,codec {
> +                       sound-dai = <&es8388>;
> +                       system-clock-frequency = <12288000>;
> +               };
> +       };
> +
> +       pwm-leds {
> +               compatible = "pwm-leds";
> +
> +               led {
> +                       color = <LED_COLOR_ID_GREEN>;
> +                       function = LED_FUNCTION_STATUS;
> +                       linux,default-trigger = "heartbeat";
> +                       max-brightness = <255>;
> +                       pwms = <&pwm0 0 25000 0>;
> +               };
> +       };
> +};
> +
> +&gmac1 {
> +       clock_in_out = "output";
> +       phy-handle = <&rgmii_phy1>;
> +       phy-mode = "rgmii-rxid";
> +       pinctrl-0 = <&gmac1_miim
> +                       &gmac1_tx_bus2
> +                       &gmac1_rx_bus2
> +                       &gmac1_rgmii_clk
> +                       &gmac1_rgmii_bus>;
> +       pinctrl-names = "default";
> +       tx_delay = <0x42>;
> +       status = "okay";
> +};
> +
> +&i2c6 {
> +       es8388: audio-codec@10 {
> +               compatible = "everest,es8388", "everest,es8328";
> +               reg = <0x10>;
> +               clocks = <&cru I2S1_8CH_MCLKOUT>;
> +               AVDD-supply = <&vcca_3v3_s0>;
> +               DVDD-supply = <&vcca_1v8_s0>;
> +               HPVDD-supply = <&vcca_3v3_s0>;
> +               PVDD-supply = <&vcca_3v3_s0>;
> +               assigned-clocks = <&cru I2S1_8CH_MCLKOUT>;
> +               assigned-clock-rates = <12288000>;
> +               #sound-dai-cells = <0>;
> +       };
> +
> +       usbc0: usb-typec@22 {
> +               compatible = "fcs,fusb302";
> +               reg = <0x22>;
> +               interrupt-parent = <&gpio0>;
> +               interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&usbc0_int>;
> +               vbus-supply = <&vbus_typec>;
> +               status = "okay";
> +
> +               usb_con: connector {
> +                       compatible = "usb-c-connector";
> +                       label = "USB-C";
> +                       data-role = "dual";
> +                       op-sink-microwatt = <1000000>;
> +                       power-role = "dual";
> +                       sink-pdos =
> +                               <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
> +                       source-pdos =
> +                               <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
> +                       try-power-role = "source";
> +
> +                       ports {
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               port@0 {
> +                                       reg = <0>;
> +                                       usbc0_hs: endpoint {
> +                                               remote-endpoint = <&usb_host0_xhci_drd_sw>;
> +                                       };
> +                               };
> +
> +                               port@1 {
> +                                       reg = <1>;
> +                                       usbc0_ss: endpoint {
> +                                               remote-endpoint = <&usbdp_phy0_typec_ss>;
> +                                       };
> +                               };
> +
> +                               port@2 {
> +                                       reg = <2>;
> +                                       usbc0_sbu: endpoint {
> +                                               remote-endpoint = <&usbdp_phy0_typec_sbu>;
> +                                       };
> +                               };
> +                       };
> +               };
> +       };
> +};
> +
> +&i2s1_8ch {
> +       rockchip,i2s-tx-route = <3 2 1 0>;
> +       rockchip,i2s-rx-route = <1 3 2 0>;
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&i2s1m0_sclk
> +                          &i2s1m0_mclk
> +                          &i2s1m0_lrck
> +                          &i2s1m0_sdi1
> +                          &i2s1m0_sdo3>;
> +       status = "okay";
> +};
> +
> +&pwm0 {
> +       pinctrl-0 = <&pwm0m2_pins>;
> +       pinctrl-names = "default";
> +       status = "okay";
> +};
> +
> +&rk806_single {
> +       regulators {
> +               vcc_1v8_s0: pldo-reg1 {
> +                       regulator-name = "vcc_1v8_s0";
> +                       regulator-always-on;
> +                       regulator-boot-on;
> +                       regulator-min-microvolt = <1800000>;
> +                       regulator-max-microvolt = <1800000>;
> +
> +                       regulator-state-mem {
> +                               regulator-off-in-suspend;
> +                       };
> +               };
> +
> +               vcca_1v8_s0: pldo-reg2 {
> +                       regulator-name = "vcca_1v8_s0";
> +                       regulator-always-on;
> +                       regulator-boot-on;
> +                       regulator-min-microvolt = <1800000>;
> +                       regulator-max-microvolt = <1800000>;
> +
> +                       regulator-state-mem {
> +                               regulator-off-in-suspend;
> +                               regulator-suspend-microvolt = <1800000>;
> +                       };
> +               };
> +       };
> +};
> +
> +
> +&usb_host0_xhci {
> +       dr_mode = "otg";
> +       usb-role-switch;
> +
> +       port {
> +               usb_host0_xhci_drd_sw: endpoint {
> +                       remote-endpoint = <&usbc0_hs>;
> +               };
> +       };
> +};
> +
> +&usb_host2_xhci {
> +       status = "okay";
> +};
> +
> +&usbdp_phy0 {
> +       mode-switch;
> +       orientation-switch;
> +       sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
> +       sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
> +
> +       port {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               usbdp_phy0_typec_ss: endpoint@0 {
> +                       reg = <0>;
> +                       remote-endpoint = <&usbc0_ss>;
> +               };
> +
> +               usbdp_phy0_typec_sbu: endpoint@1 {
> +                       reg = <1>;
> +                       remote-endpoint = <&usbc0_sbu>;
> +               };
> +       };
> +};
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
> index 83b9b6645a1e..d76bdf1b5e90 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
> @@ -2,12 +2,16 @@
>
>  /dts-v1/;
>
> -#include "rk3588s-orangepi-5.dtsi"
> +#include "rk3588s-orangepi-5-5b.dtsi"
>
>  / {
>         model = "Xunlong Orange Pi 5";
>         compatible = "xunlong,orangepi-5", "rockchip,rk3588s";
>
> +       aliases {
> +               mmc0 = &sdmmc;
> +       };
> +
>         vcc3v3_pcie20: regulator-vcc3v3-pcie20 {
>                 compatible = "regulator-fixed";
>                 enable-active-high;
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
> index fd5c6a025cd1..2b605e5fc35a 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
> @@ -3,19 +3,13 @@
>  /dts-v1/;
>
>  #include <dt-bindings/gpio/gpio.h>
> -#include <dt-bindings/leds/common.h>
>  #include <dt-bindings/input/input.h>
> +#include <dt-bindings/leds/common.h>
>  #include <dt-bindings/pinctrl/rockchip.h>
>  #include <dt-bindings/soc/rockchip,vop2.h>
> -#include <dt-bindings/usb/pd.h>
>  #include "rk3588s.dtsi"
>
>  / {
> -       aliases {
> -               ethernet0 = &gmac1;
> -               mmc0 = &sdmmc;
> -       };
> -
>         chosen {
>                 stdout-path = "serial2:1500000n8";
>         };
> @@ -34,38 +28,6 @@ button-recovery {
>                 };
>         };
>
> -       analog-sound {
> -               compatible = "simple-audio-card";
> -               pinctrl-names = "default";
> -               pinctrl-0 = <&hp_detect>;
> -               simple-audio-card,name = "rockchip,es8388";
> -               simple-audio-card,bitclock-master = <&masterdai>;
> -               simple-audio-card,format = "i2s";
> -               simple-audio-card,frame-master = <&masterdai>;
> -               simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
> -               simple-audio-card,mclk-fs = <256>;
> -               simple-audio-card,routing =
> -                       "Headphones", "LOUT1",
> -                       "Headphones", "ROUT1",
> -                       "LINPUT1", "Microphone Jack",
> -                       "RINPUT1", "Microphone Jack",
> -                       "LINPUT2", "Onboard Microphone",
> -                       "RINPUT2", "Onboard Microphone";
> -               simple-audio-card,widgets =
> -                       "Microphone", "Microphone Jack",
> -                       "Microphone", "Onboard Microphone",
> -                       "Headphone", "Headphones";
> -
> -               simple-audio-card,cpu {
> -                       sound-dai = <&i2s1_8ch>;
> -               };
> -
> -               masterdai: simple-audio-card,codec {
> -                       sound-dai = <&es8388>;
> -                       system-clock-frequency = <12288000>;
> -               };
> -       };
> -
>         hdmi0-con {
>                 compatible = "hdmi-connector";
>                 type = "a";
> @@ -77,18 +39,6 @@ hdmi0_con_in: endpoint {
>                 };
>         };
>
> -       pwm-leds {
> -               compatible = "pwm-leds";
> -
> -               led {
> -                       color = <LED_COLOR_ID_GREEN>;
> -                       function = LED_FUNCTION_STATUS;
> -                       linux,default-trigger = "heartbeat";
> -                       max-brightness = <255>;
> -                       pwms = <&pwm0 0 25000 0>;
> -               };
> -       };
> -
>         vbus_typec: regulator-vbus-typec {
>                 compatible = "regulator-fixed";
>                 enable-active-high;
> @@ -101,15 +51,6 @@ vbus_typec: regulator-vbus-typec {
>                 vin-supply = <&vcc5v0_sys>;
>         };
>
> -       vcc5v0_sys: regulator-vcc5v0-sys {
> -               compatible = "regulator-fixed";
> -               regulator-name = "vcc5v0_sys";
> -               regulator-always-on;
> -               regulator-boot-on;
> -               regulator-min-microvolt = <5000000>;
> -               regulator-max-microvolt = <5000000>;
> -       };
> -
>         vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
>                 compatible = "regulator-fixed";
>                 gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
> @@ -119,6 +60,15 @@ vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
>                 regulator-max-microvolt = <3300000>;
>                 vin-supply = <&vcc_3v3_s3>;
>         };
> +
> +       vcc5v0_sys: regulator-vcc5v0-sys {
> +               compatible = "regulator-fixed";
> +               regulator-name = "vcc5v0_sys";
> +               regulator-always-on;
> +               regulator-boot-on;
> +               regulator-min-microvolt = <5000000>;
> +               regulator-max-microvolt = <5000000>;
> +       };
>  };
>
>  &combphy0_ps {
> @@ -161,20 +111,6 @@ &cpu_l3 {
>         cpu-supply = <&vdd_cpu_lit_s0>;
>  };
>
> -&gmac1 {
> -       clock_in_out = "output";
> -       phy-handle = <&rgmii_phy1>;
> -       phy-mode = "rgmii-rxid";
> -       pinctrl-0 = <&gmac1_miim
> -                    &gmac1_tx_bus2
> -                    &gmac1_rx_bus2
> -                    &gmac1_rgmii_clk
> -                    &gmac1_rgmii_bus>;
> -       pinctrl-names = "default";
> -       tx_delay = <0x42>;
> -       status = "okay";
> -};
> -
>  &gpu {
>         mali-supply = <&vdd_gpu_s0>;
>         status = "okay";
> @@ -270,69 +206,6 @@ &i2c6 {
>         pinctrl-0 = <&i2c6m3_xfer>;
>         status = "okay";
>
> -       es8388: audio-codec@10 {
> -               compatible = "everest,es8388", "everest,es8328";
> -               reg = <0x10>;
> -               clocks = <&cru I2S1_8CH_MCLKOUT>;
> -               AVDD-supply = <&vcca_3v3_s0>;
> -               DVDD-supply = <&vcca_1v8_s0>;
> -               HPVDD-supply = <&vcca_3v3_s0>;
> -               PVDD-supply = <&vcca_3v3_s0>;
> -               assigned-clocks = <&cru I2S1_8CH_MCLKOUT>;
> -               assigned-clock-rates = <12288000>;
> -               #sound-dai-cells = <0>;
> -       };
> -
> -       usbc0: usb-typec@22 {
> -               compatible = "fcs,fusb302";
> -               reg = <0x22>;
> -               interrupt-parent = <&gpio0>;
> -               interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
> -               pinctrl-names = "default";
> -               pinctrl-0 = <&usbc0_int>;
> -               vbus-supply = <&vbus_typec>;
> -               status = "okay";
> -
> -               usb_con: connector {
> -                       compatible = "usb-c-connector";
> -                       label = "USB-C";
> -                       data-role = "dual";
> -                       op-sink-microwatt = <1000000>;
> -                       power-role = "dual";
> -                       sink-pdos =
> -                               <PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
> -                       source-pdos =
> -                               <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
> -                       try-power-role = "source";
> -
> -                       ports {
> -                               #address-cells = <1>;
> -                               #size-cells = <0>;
> -
> -                               port@0 {
> -                                       reg = <0>;
> -                                       usbc0_hs: endpoint {
> -                                               remote-endpoint = <&usb_host0_xhci_drd_sw>;
> -                                       };
> -                               };
> -
> -                               port@1 {
> -                                       reg = <1>;
> -                                       usbc0_ss: endpoint {
> -                                               remote-endpoint = <&usbdp_phy0_typec_ss>;
> -                                       };
> -                               };
> -
> -                               port@2 {
> -                                       reg = <2>;
> -                                       usbc0_sbu: endpoint {
> -                                               remote-endpoint = <&usbdp_phy0_typec_sbu>;
> -                                       };
> -                               };
> -                       };
> -               };
> -       };
> -
>         hym8563: rtc@51 {
>                 compatible = "haoyu,hym8563";
>                 reg = <0x51>;
> @@ -346,18 +219,6 @@ hym8563: rtc@51 {
>         };
>  };
>
> -&i2s1_8ch {
> -       rockchip,i2s-tx-route = <3 2 1 0>;
> -       rockchip,i2s-rx-route = <1 3 2 0>;
> -       pinctrl-names = "default";
> -       pinctrl-0 = <&i2s1m0_sclk
> -                    &i2s1m0_mclk
> -                    &i2s1m0_lrck
> -                    &i2s1m0_sdi1
> -                    &i2s1m0_sdo3>;
> -       status = "okay";
> -};
> -
>  &i2s5_8ch {
>         status = "okay";
>  };
> @@ -404,12 +265,6 @@ typec5v_pwren: typec5v-pwren {
>         };
>  };
>
> -&pwm0 {
> -       pinctrl-0 = <&pwm0m2_pins>;
> -       pinctrl-names = "default";
> -       status = "okay";
> -};
> -
>  &rknn_core_0 {
>         npu-supply = <&vdd_npu_s0>;
>         sram-supply = <&vdd_npu_s0>;
> @@ -491,7 +346,7 @@ &spi2 {
>         pinctrl-names = "default";
>         pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
>
> -       pmic@0 {
> +       rk806_single: pmic@0 {
>                 compatible = "rockchip,rk806";
>                 reg = <0x0>;
>                 interrupt-parent = <&gpio0>;
> @@ -666,31 +521,6 @@ regulator-state-mem {
>                                 };
>                         };
>
> -                       vcc_1v8_s0: pldo-reg1 {
> -                               regulator-name = "vcc_1v8_s0";
> -                               regulator-always-on;
> -                               regulator-boot-on;
> -                               regulator-min-microvolt = <1800000>;
> -                               regulator-max-microvolt = <1800000>;
> -
> -                               regulator-state-mem {
> -                                       regulator-off-in-suspend;
> -                               };
> -                       };
> -
> -                       vcca_1v8_s0: pldo-reg2 {
> -                               regulator-name = "vcca_1v8_s0";
> -                               regulator-always-on;
> -                               regulator-boot-on;
> -                               regulator-min-microvolt = <1800000>;
> -                               regulator-max-microvolt = <1800000>;
> -
> -                               regulator-state-mem {
> -                                       regulator-off-in-suspend;
> -                                       regulator-suspend-microvolt = <1800000>;
> -                               };
> -                       };
> -
>                         vdda_1v2_s0: pldo-reg3 {
>                                 regulator-name = "vdda_1v2_s0";
>                                 regulator-always-on;
> @@ -841,26 +671,7 @@ &uart2 {
>  };
>
>  &usbdp_phy0 {
> -       mode-switch;
> -       orientation-switch;
> -       sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
> -       sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
>         status = "okay";
> -
> -       port {
> -               #address-cells = <1>;
> -               #size-cells = <0>;
> -
> -               usbdp_phy0_typec_ss: endpoint@0 {
> -                       reg = <0>;
> -                       remote-endpoint = <&usbc0_ss>;
> -               };
> -
> -               usbdp_phy0_typec_sbu: endpoint@1 {
> -                       reg = <1>;
> -                       remote-endpoint = <&usbc0_sbu>;
> -               };
> -       };
>  };
>
>  &usb_host0_ehci {
> @@ -872,15 +683,7 @@ &usb_host0_ohci {
>  };
>
>  &usb_host0_xhci {
> -       dr_mode = "otg";
> -       usb-role-switch;
>         status = "okay";
> -
> -       port {
> -               usb_host0_xhci_drd_sw: endpoint {
> -                       remote-endpoint = <&usbc0_hs>;
> -               };
> -       };
>  };
>
>  &usb_host1_ehci {
> @@ -891,7 +694,7 @@ &usb_host1_ohci {
>         status = "okay";
>  };
>
> -&usb_host2_xhci {
> +&vop {
>         status = "okay";
>  };
>
> @@ -899,10 +702,6 @@ &vop_mmu {
>         status = "okay";
>  };
>
> -&vop {
> -       status = "okay";
> -};
> -
>  &vp0 {
>         vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
>                 reg = <ROCKCHIP_VOP2_EP_HDMI0>;
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
> index d21ec320d295..8af174777809 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
> @@ -2,7 +2,7 @@
>
>  /dts-v1/;
>
> -#include "rk3588s-orangepi-5.dtsi"
> +#include "rk3588s-orangepi-5-5b.dtsi"
>
>  / {
>         model = "Xunlong Orange Pi 5B";
> --
> 2.53.0
>

^ permalink raw reply

* Re: [PATCH v2 1/7] dt-bindings: spi: qcom,spi-qcom-qspi: Add qcom,qcs615-qspi compatible
From: Krzysztof Kozlowski @ 2026-04-15  7:56 UTC (permalink / raw)
  To: Viken Dadhaniya
  Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, cros-qcom-dts-watchers,
	linux-arm-msm, linux-spi, devicetree, linux-kernel
In-Reply-To: <20260414-spi-nor-v2-1-bcca40de4b5f@oss.qualcomm.com>

On Tue, Apr 14, 2026 at 10:38:19PM +0530, Viken Dadhaniya wrote:
> +allOf:
> +  - $ref: /schemas/spi/spi-controller.yaml#
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: qcom,qcs615-qspi
> +    then:
> +      properties:
> +        interconnects:
> +          minItems: 2

Missing constraint for interconnect-names


Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 1/2] dt-bindings: media: i2c: Add os02g10 sensor
From: Krzysztof Kozlowski @ 2026-04-15  7:54 UTC (permalink / raw)
  To: Elgin Perumbilly
  Cc: sakari.ailus, tarang.raval, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Hans Verkuil, Hans de Goede,
	Vladimir Zapolskiy, Mehdi Djait, Laurent Pinchart,
	Benjamin Mugnier, Sylvain Petinot, Hardevsinh Palaniya,
	Heimir Thor Sverrisson, Jingjing Xiong, Himanshu Bhavani,
	Svyatoslav Ryhel, linux-media, devicetree, linux-kernel
In-Reply-To: <20260414084952.217215-2-elgin.perumbilly@siliconsignals.io>

On Tue, Apr 14, 2026 at 02:19:44PM +0530, Elgin Perumbilly wrote:
> Add bindings for Omnivision OS02G10 sensor.
> 
> Signed-off-by: Elgin Perumbilly <elgin.perumbilly@siliconsignals.io>
> ---
>  .../bindings/media/i2c/ovti,os02g10.yaml      | 96 +++++++++++++++++++
>  MAINTAINERS                                   |  7 ++
>  2 files changed, 103 insertions(+)

Your changelog in cover letters says nothing changed here, so same
comments as v1. Please go back to v1 and read the feedback carefully.

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH 2/2] arm64: dts: qcom: glymur-crd: Drop forced host mode for USB SS0 and SS1
From: Abel Vesa @ 2026-04-15  7:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Wesley Cheng, Dmitry Baryshkov
  Cc: Konrad Dybcio, linux-arm-msm, devicetree, linux-kernel, Abel Vesa
In-Reply-To: <20260415-dts-qcom-glymur-usb-role-switch-fix-v1-0-409e1a257f1f@oss.qualcomm.com>

The two USB Type-C ports on Glymur CRD are dual-role capable.

Do not force their controllers into host mode. Drop the explicit
'dr_mode = "host"' properties so they can use their default OTG mode
instead.

Fixes: c8b63029455b ("arm64: dts: qcom: glymur-crd: Enable USB support")
Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/glymur-crd.dts | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dts b/arch/arm64/boot/dts/qcom/glymur-crd.dts
index 35aaf09e4e2b..c98dfb3941fa 100644
--- a/arch/arm64/boot/dts/qcom/glymur-crd.dts
+++ b/arch/arm64/boot/dts/qcom/glymur-crd.dts
@@ -322,8 +322,6 @@ reset-n-pins {
 };
 
 &usb_0 {
-	dr_mode = "host";
-
 	status = "okay";
 };
 
@@ -353,8 +351,6 @@ &usb_0_qmpphy_out {
 };
 
 &usb_1 {
-	dr_mode = "host";
-
 	status = "okay";
 };
 

-- 
2.48.1


^ permalink raw reply related

* [PATCH 1/2] arm64: dts: qcom: glymur: Mark USB SS1 and SS2 as role-switch capable
From: Abel Vesa @ 2026-04-15  7:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Wesley Cheng, Dmitry Baryshkov
  Cc: Konrad Dybcio, linux-arm-msm, devicetree, linux-kernel, Abel Vesa
In-Reply-To: <20260415-dts-qcom-glymur-usb-role-switch-fix-v1-0-409e1a257f1f@oss.qualcomm.com>

Like USB SS0, the USB SS1 and SS2 controllers on Glymur also support
USB role switching.

Describe this by adding the 'usb-role-switch' property to both controllers.

Fixes: 4eee57dd4df9 ("arm64: dts: qcom: glymur: Add USB related nodes")
Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/glymur.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
index f23cf81ddb77..0251ff43d594 100644
--- a/arch/arm64/boot/dts/qcom/glymur.dtsi
+++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
@@ -3928,6 +3928,8 @@ usb_1: usb@a800000 {
 			snps,dis_u2_susphy_quirk;
 			snps,dis_enblslpm_quirk;
 
+			usb-role-switch;
+
 			status = "disabled";
 
 			ports {
@@ -4001,6 +4003,8 @@ usb_2: usb@a000000 {
 			snps,dis_u2_susphy_quirk;
 			snps,dis_enblslpm_quirk;
 
+			usb-role-switch;
+
 			status = "disabled";
 
 			ports {

-- 
2.48.1


^ permalink raw reply related

* [PATCH 0/2] arm64: dts: qcom: glymur: Fix USB role-switch configuration
From: Abel Vesa @ 2026-04-15  7:52 UTC (permalink / raw)
  To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Wesley Cheng, Dmitry Baryshkov
  Cc: Konrad Dybcio, linux-arm-msm, devicetree, linux-kernel, Abel Vesa

The Glymur USB role-switch description is currently incomplete and partly
self-contradictory.

At the SoC level, only USB SS0 is currently described as being able to
switch USB data role, while SS1 and SS2 are missing the 'usb-role-switch'
property even though the controllers support it.

At the board level, Glymur CRD forces the two exposed Type-C ports into
host mode through 'dr_mode = "host"', which prevents them from behaving
as dual-role ports.

Fix this by first marking the additional Glymur USB controllers as role
switch capable, then by dropping the forced host mode from the two CRD
Type-C ports so that they can operate in their natural OTG mode.

This restores the intended dual-role behavior for the exposed USB-C
ports on Glymur CRD.

Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
---
Abel Vesa (2):
      arm64: dts: qcom: glymur: Mark USB SS1 and SS2 as role-switch capable
      arm64: dts: qcom: glymur-crd: Drop forced host mode for USB SS0 and SS1

 arch/arm64/boot/dts/qcom/glymur-crd.dts | 4 ----
 arch/arm64/boot/dts/qcom/glymur.dtsi    | 4 ++++
 2 files changed, 4 insertions(+), 4 deletions(-)
---
base-commit: e6efabc0afca02efa263aba533f35d90117ab283
change-id: 20260415-dts-qcom-glymur-usb-role-switch-fix-fce43098888c

Best regards,
--  
Abel Vesa <abel.vesa@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH v3 1/5] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add support for glymur Gen5 x8 bifurcation mode
From: Krzysztof Kozlowski @ 2026-04-15  7:50 UTC (permalink / raw)
  To: Qiang Yu
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio,
	linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-1-affcebc16b8b@oss.qualcomm.com>

On Sun, Apr 12, 2026 at 11:25:56PM -0700, Qiang Yu wrote:
> The Glymur SoC has pcie3a and pcie3b PHYs that can operate in two modes:
> 
> 1. Independent 4-lane mode: Each PHY operates as a separate PCIe Gen5
>    4-lane interface, compatible with qcom,glymur-qmp-gen5x4-pcie-phy
> 2. Bifurcation mode (8-lane): pcie3a phy acts as leader and pcie3b phy as
>    follower to form a single 8-lane PCIe Gen5 interface
> 
> In bifurcation mode, the hardware design requires controlling additional
> resources beyond the standard pcie3a PHY configuration:
> 
> - pcie3b's aux_clk (phy_b_aux)
> - pcie3b's phy_gdsc power domain
> - pcie3b's bcr/nocsr reset
> 
> Add qcom,glymur-qmp-gen5x8-pcie-phy compatible string to document this
> 8-lane bifurcation configuration.

Do you describe PCI3A or PCI3B or something combined PCI3?

> 
> The phy_b_aux clock is used as the 6th clock instead of pipediv2,
> requiring the clock-names enum to be extended to support both
> [phy_b_aux, pipediv2] options at index 5. This follows the existing
> pattern used for [rchng, refgen] clocks at index 3.
> 
> Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
> ---
>  .../bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml   | 53 ++++++++++++++++++----
>  1 file changed, 45 insertions(+), 8 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
> index 3a35120a77ec0ceb814a1cdcacff32fef32b4f7b..14eba5d705b1956c1bb00cc8c95171ed6488299b 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
> @@ -18,6 +18,7 @@ properties:
>      enum:
>        - qcom,glymur-qmp-gen4x2-pcie-phy
>        - qcom,glymur-qmp-gen5x4-pcie-phy
> +      - qcom,glymur-qmp-gen5x8-pcie-phy

That's the same device as 5x4, no? One device, one compatible and this
suggests you will have three PCI phys in the DT - two 5x4 and one 5x8?


>        - qcom,kaanapali-qmp-gen3x2-pcie-phy
>        - qcom,qcs615-qmp-gen3x1-pcie-phy
>        - qcom,qcs8300-qmp-gen4x2-pcie-phy
> @@ -68,20 +69,27 @@ properties:
>        - const: ref
>        - enum: [rchng, refgen]
>        - const: pipe
> -      - const: pipediv2
> +      - enum: [phy_b_aux, pipediv2]
>  
>    power-domains:
> -    maxItems: 1
> +    minItems: 1
> +    items:
> +      - description: PCIe PHY power domain. For PHYs supporting
> +          bifurcation mode, this is the leader PHY power domain.
> +      - description: Additional PCIe PHY power domain for PHYs supporting
> +          bifurcation mode, used by the follower PHY.
>  
>    resets:
>      minItems: 1
> -    maxItems: 2
> +    maxItems: 4
>  
>    reset-names:
>      minItems: 1
>      items:
>        - const: phy
>        - const: phy_nocsr
> +      - const: phy_b
> +      - const: phy_b_nocsr

And now I doubt that all the changes here are for duplicated node.

Maybe just the commit msg is confusing and instead of describing some
node which combines two other phys just say what device is here being
described.

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH v3 3/3] remoteproc: imx_rproc: Add support for i.MX94
From: Peng Fan (OSS) @ 2026-04-15  7:50 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan
In-Reply-To: <20260415-imx943-rproc-v3-0-9fa7528db8ca@nxp.com>

From: Peng Fan <peng.fan@nxp.com>

Add basic remoteproc support for the i.MX94 M-core processors, including
address translation tables(dev addr is from view of remote processor,
sys addr is from view of main processor) and device configuration data for
the CM70, CM71, and CM33S cores.

Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/remoteproc/imx_rproc.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index c21782be4bb69d830479f538a091bda48b740ca4..5c4a1f2f877f5afd82192a13281f57f094a0e478 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -145,6 +145,47 @@ static const struct imx_rproc_att imx_rproc_att_imx95_m7[] = {
 	{ 0x80000000, 0x80000000, 0x50000000, 0 },
 };
 
+static const struct imx_rproc_att imx_rproc_att_imx94_m70[] = {
+	/* dev addr , sys addr  , size	    , flags */
+	/* TCM CODE NON-SECURE */
+	{ 0x00000000, 0x203C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM SYS NON-SECURE*/
+	{ 0x20000000, 0x20400000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* DDR */
+	{ 0x80000000, 0x80000000, 0x50000000, 0 },
+};
+
+static const struct imx_rproc_att imx_rproc_att_imx94_m71[] = {
+	/* dev addr , sys addr  , size	    , flags */
+	/* TCM CODE NON-SECURE */
+	{ 0x00000000, 0x202C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM SYS NON-SECURE*/
+	{ 0x20000000, 0x20300000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* DDR */
+	{ 0x80000000, 0x80000000, 0x50000000, 0 },
+};
+
+static const struct imx_rproc_att imx_rproc_att_imx94_m33s[] = {
+	/* dev addr , sys addr  , size	    , flags */
+	/* TCM CODE NON-SECURE */
+	{ 0x0FFC0000, 0x209C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM CODE SECURE */
+	{ 0x1FFC0000, 0x209C0000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* TCM SYS NON-SECURE */
+	{ 0x20000000, 0x20A00000, 0x00040000, ATT_OWN | ATT_IOMEM },
+	/* TCM SYS SECURE */
+	{ 0x30000000, 0x20A00000, 0x00040000, ATT_OWN | ATT_IOMEM },
+
+	/* M33S OCRAM */
+	{ 0x20800000, 0x20800000, 0x180000, ATT_OWN | ATT_IOMEM },
+
+	/* DDR */
+	{ 0x80000000, 0x80000000, 0x50000000, 0 },
+};
+
 static const struct imx_rproc_att imx_rproc_att_imx93[] = {
 	/* dev addr , sys addr  , size	    , flags */
 	/* TCM CODE NON-SECURE */
@@ -1477,6 +1518,33 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
 	.flags		= IMX_RPROC_NEED_CLKS,
 };
 
+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m70 = {
+	.att		= imx_rproc_att_imx94_m70,
+	.att_size	= ARRAY_SIZE(imx_rproc_att_imx94_m70),
+	.ops		= &imx_rproc_ops_sm_lmm,
+	.cpuid		= 1,
+	.lmid		= 2,
+	.reset_vector_mask = GENMASK_U32(31, 16),
+};
+
+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m71 = {
+	.att		= imx_rproc_att_imx94_m71,
+	.att_size	= ARRAY_SIZE(imx_rproc_att_imx94_m71),
+	.ops		= &imx_rproc_ops_sm_lmm,
+	.cpuid		= 7,
+	.lmid		= 3,
+	.reset_vector_mask = GENMASK_U32(31, 16),
+};
+
+static const struct imx_rproc_dcfg imx_rproc_cfg_imx94_m33s = {
+	.att		= imx_rproc_att_imx94_m33s,
+	.att_size	= ARRAY_SIZE(imx_rproc_att_imx94_m33s),
+	.ops		= &imx_rproc_ops_sm_lmm,
+	.cpuid		= 8,
+	.lmid		= 1,
+	.reset_vector_mask = GENMASK_U32(31, 16),
+};
+
 static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = {
 	.att		= imx_rproc_att_imx95_m7,
 	.att_size	= ARRAY_SIZE(imx_rproc_att_imx95_m7),
@@ -1501,6 +1569,9 @@ static const struct of_device_id imx_rproc_of_match[] = {
 	{ .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm },
 	{ .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
 	{ .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
+	{ .compatible = "fsl,imx94-cm70", .data = &imx_rproc_cfg_imx94_m70 },
+	{ .compatible = "fsl,imx94-cm71", .data = &imx_rproc_cfg_imx94_m71 },
+	{ .compatible = "fsl,imx94-cm33s", .data = &imx_rproc_cfg_imx94_m33s },
 	{ .compatible = "fsl,imx95-cm7", .data = &imx_rproc_cfg_imx95_m7 },
 	{},
 };

-- 
2.37.1


^ permalink raw reply related

* [PATCH v3 2/3] remoteproc: imx_rproc: Program non-zero SM CPU/LMM reset vector
From: Peng Fan (OSS) @ 2026-04-15  7:50 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan
In-Reply-To: <20260415-imx943-rproc-v3-0-9fa7528db8ca@nxp.com>

From: Peng Fan <peng.fan@nxp.com>

Cortex-M[7,33] processors use a fixed reset vector table format:

  0x00  Initial SP value
  0x04  Reset vector
  0x08  NMI
  0x0C  ...
  ...
  IRQ[n]

In ELF images, the corresponding layout is:

reset_vectors:  --> hardware reset address
        .word __stack_end__
        .word Reset_Handler
        .word NMI_Handler
        .word HardFault_Handler
        ...
        .word UART_IRQHandler
        .word SPI_IRQHandler
        ...

Reset_Handler:  --> ELF entry point address
        ...

The hardware fetches the first two words from reset_vectors and populates
SP with __stack_end__ and PC with Reset_Handler. Execution proceeds from
Reset_Handler.

However, the ELF entry point does not always match the hardware reset
address. For example, on i.MX94 CM33S:

  ELF entry point:     0x0ffc211d
  hardware reset base: 0x0ffc0000 (default reset value, sw programmable)

Current driver always programs the reset vector as 0. But i.MX94 CM33S's
default reset base is 0x0ffc0000, so the correct reset vector must be
passed to the SM API; otherwise the M33 Sync core cannot boot successfully.

rproc_elf_get_boot_addr() returns the ELF entry point, which is not the
hardware reset vector address. Fix the issue by deriving the hardware reset
vector locally using a SoC-specific mask:

  reset_vector = rproc->bootaddr & reset_vector_mask

The ELF entry point semantics remain unchanged. The masking is applied only
at the point where the SM reset vector is programmed.

Add reset_vector_mask = GENMASK_U32(31, 16) to the i.MX95 M7 configuration
so the hardware reset vector is derived correctly. Without this mask, the
SM reset vector would be programmed with an unaligned ELF entry point and
the M7 core would fail to boot.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/remoteproc/imx_rproc.c | 27 +++++++++++++++++++++++++--
 drivers/remoteproc/imx_rproc.h |  2 ++
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 0dd80e688b0ea3df4c66e5726884dc86c8a5a881..c21782be4bb69d830479f538a091bda48b740ca4 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -339,13 +339,32 @@ static int imx_rproc_scu_api_start(struct rproc *rproc)
 	return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry);
 }
 
+static u64 imx_rproc_sm_get_reset_vector(struct rproc *rproc)
+{
+	struct imx_rproc *priv = rproc->priv;
+	u32 reset_vector_mask = priv->dcfg->reset_vector_mask ?: GENMASK(31, 0);
+
+	/*
+	 * The hardware fetches the first two words from reset_vectors
+	 * (hardware reset address) and populates SP and PC using the first
+	 * two words. Execution proceeds from PC. The ELF entry point does
+	 * not always match the hardware reset address.
+	 * To derive the correct hardware reset address, the lower address
+	 * bits must be masked off before programming the reset vector.
+	 */
+	return rproc->bootaddr & reset_vector_mask;
+}
+
 static int imx_rproc_sm_cpu_start(struct rproc *rproc)
 {
 	struct imx_rproc *priv = rproc->priv;
 	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
+	u64 reset_vector;
 	int ret;
 
-	ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false);
+	reset_vector = imx_rproc_sm_get_reset_vector(rproc);
+
+	ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, reset_vector, true, false, false);
 	if (ret) {
 		dev_err(priv->dev, "Failed to set reset vector cpuid(%u): %d\n", dcfg->cpuid, ret);
 		return ret;
@@ -359,13 +378,16 @@ static int imx_rproc_sm_lmm_start(struct rproc *rproc)
 	struct imx_rproc *priv = rproc->priv;
 	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
 	struct device *dev = priv->dev;
+	u64 reset_vector;
 	int ret;
 
+	reset_vector = imx_rproc_sm_get_reset_vector(rproc);
+
 	/*
 	 * If the remoteproc core can't start the M7, it will already be
 	 * handled in imx_rproc_sm_lmm_prepare().
 	 */
-	ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0);
+	ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, reset_vector);
 	if (ret) {
 		dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n",
 			dcfg->lmid, dcfg->cpuid, ret);
@@ -1462,6 +1484,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = {
 	/* Must align with System Manager Firmware */
 	.cpuid		= 1, /* Use 1 as cpu id for M7 core */
 	.lmid		= 1, /* Use 1 as Logical Machine ID where M7 resides */
+	.reset_vector_mask = GENMASK_U32(31, 16),
 };
 
 static const struct of_device_id imx_rproc_of_match[] = {
diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h
index d37e6f90548cec727b4aeb874680b42af85bdbb4..0d7d48352a1091ad24e8e083172ce6da6d26ae10 100644
--- a/drivers/remoteproc/imx_rproc.h
+++ b/drivers/remoteproc/imx_rproc.h
@@ -41,6 +41,8 @@ struct imx_rproc_dcfg {
 	/* For System Manager(SM) based SoCs */
 	u32				cpuid; /* ID of the remote core */
 	u32				lmid;  /* ID of the Logcial Machine */
+	/* reset_vector = elf_entry_addr & reset_vector_mask */
+	u32				reset_vector_mask;
 };
 
 #endif /* _IMX_RPROC_H */

-- 
2.37.1


^ permalink raw reply related

* [PATCH v3 1/3] dt-bindings: remoteproc: imx-rproc: Support i.MX94
From: Peng Fan (OSS) @ 2026-04-15  7:50 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan
In-Reply-To: <20260415-imx943-rproc-v3-0-9fa7528db8ca@nxp.com>

From: Peng Fan <peng.fan@nxp.com>

Add compatible string for:
 Cortex-M7 core[0,1] in i.MX94
 Cortex-M33 Sync core in i.MX94

To i.MX94, Cortex-M7 core0 and core1 have different memory view from
Cortex-A55 core, so different compatible string is used.

Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
index ce8ec0119469c8fc0979a192b6e3d3a03108d7d2..c18f71b648890da9c25a2f3309d8dbec5bb8d226 100644
--- a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
@@ -28,6 +28,9 @@ properties:
       - fsl,imx8qxp-cm4
       - fsl,imx8ulp-cm33
       - fsl,imx93-cm33
+      - fsl,imx94-cm33s
+      - fsl,imx94-cm70
+      - fsl,imx94-cm71
       - fsl,imx95-cm7
 
   clocks:

-- 
2.37.1


^ permalink raw reply related

* [PATCH v3 0/3] Add i.MX94 remoteproc support and reset vector handling improvements
From: Peng Fan (OSS) @ 2026-04-15  7:50 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Daniel Baluta
  Cc: linux-remoteproc, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan

This series adds remoteproc support for the i.MX94 family, including the
CM70, CM71, and CM33S cores, and derive the hardware reset vector for
Cortex‑M processors whose ELF entry point does not directly correspond to
the actual reset address.

Background:
Cortex‑M processors fetch their initial SP and PC from a fixed reset vector
table. While ELF images embed the entry point (e_entry), this value is
not always aligned to the hardware reset address. On platforms such as
i.MX94 CM33S, masking is required to compute the correct reset vector
address before programming the SoC reset registers.

Similarly, on i.MX95, the existing implementation always programs a reset
vector of 0x0, which only works when executing entirely from TCM. When
firmware is loaded into DDR, the driver must pass the correct reset vector
to the SM CPU/LMM interfaces.

Summary of patches:
[1]dt-bindings: remoteproc: imx-rproc: Introduce fsl,reset-vector-mask
Adds a new DT property allowing SoCs to specify a mask for deriving the
hardware reset vector from the ELF entry point.

[2]remoteproc: imx_rproc: Program non-zero SM CPU/LMM reset vector
Ensures the correct reset vector is passed to SM APIs by introducing a
helper (imx_rproc_sm_get_reset_vector()) that applies the reset‑vector
mask.

[3]remoteproc: imx_rproc: Add support for i.MX94 remoteproc
Adds address translation tables and configuration data for CM70, CM71,
and CM33S, enabling full remoteproc operation on i.MX94.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
Changes in v3:
- Patch 2: 
  Drop R-b because of changes in V3

  Following suggestion from Mathieu that apply reset vector in
  scmi_imx_[cpu,lmm]_reset_vector_set(), not change the meaning of
  rproc->bootaddr, add helper imx_rproc_sm_get_reset_vector() to get reset
  vector and use the hlper in scmi_imx_[cpu,lmm]_reset_vector_set().

  Add reset-vector-mask for i.MX95 CM7 to avoid breaking i.MX95 CM7
  boot.

- Link to v2: https://lore.kernel.org/r/20260327-imx943-rproc-v2-0-a547a3588730@nxp.com

Changes in v2:
- Drop fsl,reset-vector-mask by using fixed value in driver for per device
- Add R-b for i.MX94 dt-binding
- Update commit log to include dev addr and sys addr
- Link to v1: https://lore.kernel.org/r/20260312-imx943-rproc-v1-0-3e66596592a8@nxp.com

---
Peng Fan (3):
      dt-bindings: remoteproc: imx-rproc: Support i.MX94
      remoteproc: imx_rproc: Program non-zero SM CPU/LMM reset vector
      remoteproc: imx_rproc: Add support for i.MX94

 .../bindings/remoteproc/fsl,imx-rproc.yaml         |  3 +
 drivers/remoteproc/imx_rproc.c                     | 98 +++++++++++++++++++++-
 drivers/remoteproc/imx_rproc.h                     |  2 +
 3 files changed, 101 insertions(+), 2 deletions(-)
---
base-commit: 724699d8d0523909da51fda8d1e10c1ff867b280
change-id: 20260311-imx943-rproc-2050e00b65f7

Best regards,
-- 
Peng Fan <peng.fan@nxp.com>


^ permalink raw reply

* Re: [PATCH v3 5/5] arch: arm64: dts: qcom: Add support for PCIe3a
From: Krzysztof Kozlowski @ 2026-04-15  7:44 UTC (permalink / raw)
  To: Qiang Yu
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio,
	linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <20260412-glymur_gen5x8_phy_0413-v3-5-affcebc16b8b@oss.qualcomm.com>

On Sun, Apr 12, 2026 at 11:26:00PM -0700, Qiang Yu wrote:
> Describe PCIe3a controller and PHY. Also add required system resources
> like regulators, clocks, interrupts and registers configuration for PCIe3a.
> 
> Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>

subject: drop arch.

Please use subject prefixes matching the subsystem. You can get them for
example with 'git log --oneline -- DIRECTORY_OR_FILE' on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

> ---
>  arch/arm64/boot/dts/qcom/glymur.dtsi | 316 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 315 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
> index f23cf81ddb77a4138deeb4e00dd8b316930a2feb..c15f87c37ecbad72076a6c731f4959a1a8bd8425 100644
> --- a/arch/arm64/boot/dts/qcom/glymur.dtsi
> +++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
> @@ -736,7 +736,7 @@ gcc: clock-controller@100000 {
>  				 <0>,				/* USB 2 Phy PCIE PIPEGMUX */
>  				 <0>,				/* USB 2 Phy PIPEGMUX */
>  				 <0>,				/* USB 2 Phy SYS PCIE PIPEGMUX */
> -				 <0>,				/* PCIe 3a */
> +				 <&pcie3a_phy>,			/* PCIe 3a */
>  				 <&pcie3b_phy>,			/* PCIe 3b */
>  				 <&pcie4_phy>,			/* PCIe 4 */
>  				 <&pcie5_phy>,			/* PCIe 5 */
> @@ -3640,6 +3640,320 @@ pcie3b_port0: pcie@0 {
>  			};

...

> > +		pcie3a_phy: phy@f00000 {

Same comment as before.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 05/11] media: iris: Enable Secure PAS support with IOMMU managed by Linux
From: Mukesh Ojha @ 2026-04-15  7:41 UTC (permalink / raw)
  To: Vishnu Reddy
  Cc: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal,
	Abhinav Kumar, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joerg Roedel, Will Deacon,
	Robin Murphy, Bjorn Andersson, Konrad Dybcio, Stefan Schmidt,
	Hans Verkuil, linux-media, linux-arm-msm, devicetree,
	linux-kernel, iommu
In-Reply-To: <20260415073605.qqvpf36uhqmghg5h@hu-mojha-hyd.qualcomm.com>

On Wed, Apr 15, 2026 at 01:06:05PM +0530, Mukesh Ojha wrote:
> On Tue, Apr 14, 2026 at 12:01:28PM +0530, Mukesh Ojha wrote:
> > On Tue, Apr 14, 2026 at 10:30:01AM +0530, Vishnu Reddy wrote:
> > > From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> > > 
> > > Most Qualcomm platforms feature a proprietary hypervisor (such as Gunyah
> > > or QHEE), which typically handles IOMMU configuration. This includes
> > > mapping memory regions and device memory resources for remote processors
> > > by intercepting qcom_scm_pas_auth_and_reset() calls. These mappings are
> > > later removed during teardown. Additionally, SHM bridge setup is required
> > > to enable memory protection for both remoteproc metadata and its memory
> > > regions.
> > > 
> > > When the hypervisor is absent, the operating system must perform these
> > > configurations instead.
> > > 
> > > Support for handling IOMMU and SHM setup in the absence of a hypervisor
> > > is now in place. Extend the Iris driver to enable this functionality on
> > > platforms where IOMMU is managed by Linux (i.e., non-Gunyah, non-QHEE).
> > > 
> > > Additionally, the Iris driver must map the firmware and its required
> > > resources to the firmware SID, which is now specified via iommu-map in
> > > the device tree.
> > > 
> > > Co-developed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> > > Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> > > Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> > > Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
> > > ---
> > >  drivers/media/platform/qcom/iris/iris_core.h     |  4 ++
> > >  drivers/media/platform/qcom/iris/iris_firmware.c | 71 +++++++++++++++++++++---
> > >  2 files changed, 66 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
> > > index fb194c967ad4..aa7abef6f0e0 100644
> > > --- a/drivers/media/platform/qcom/iris/iris_core.h
> > > +++ b/drivers/media/platform/qcom/iris/iris_core.h
> > > @@ -34,6 +34,8 @@ enum domain_type {
> > >   * struct iris_core - holds core parameters valid for all instances
> > >   *
> > >   * @dev: reference to device structure
> > > + * @dev_fw: reference to the context bank device used for firmware load
> > > + * @ctx_fw: SCM PAS context for authenticated firmware load and shutdown
> > >   * @reg_base: IO memory base address
> > >   * @irq: iris irq
> > >   * @v4l2_dev: a holder for v4l2 device structure
> > > @@ -77,6 +79,8 @@ enum domain_type {
> > >  
> > >  struct iris_core {
> > >  	struct device				*dev;
> > > +	struct device				*dev_fw;
> > > +	struct qcom_scm_pas_context		*ctx_fw;
> > 
> > fw_dev suits better and ctx_fw is always for firmware, maybe pas_ctx is
> > better.
> > 
> > >  	void __iomem				*reg_base;
> > >  	int					irq;
> > >  	struct v4l2_device			v4l2_dev;
> > > diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c
> > > index 5f408024e967..93d77996c83f 100644
> > > --- a/drivers/media/platform/qcom/iris/iris_firmware.c
> > > +++ b/drivers/media/platform/qcom/iris/iris_firmware.c
> > > @@ -5,6 +5,7 @@
> > >  
> > >  #include <linux/firmware.h>
> > >  #include <linux/firmware/qcom/qcom_scm.h>
> > > +#include <linux/iommu.h>
> > >  #include <linux/of_address.h>
> > >  #include <linux/of_reserved_mem.h>
> > >  #include <linux/soc/qcom/mdt_loader.h>
> > > @@ -13,12 +14,15 @@
> > >  #include "iris_firmware.h"
> > >  
> > >  #define MAX_FIRMWARE_NAME_SIZE	128
> > > +#define IRIS_FW_START_ADDR	0
> > >  
> > >  static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> > >  {
> > > +	struct device *dev = core->dev_fw ? core->dev_fw : core->dev;
> > >  	u32 pas_id = core->iris_platform_data->pas_id;
> > >  	const struct firmware *firmware = NULL;
> > > -	struct device *dev = core->dev;
> > > +	struct qcom_scm_pas_context *ctx_fw;
> > > +	struct iommu_domain *domain;
> > >  	struct resource res;
> > >  	phys_addr_t mem_phys;
> > >  	size_t res_size;
> > > @@ -29,13 +33,17 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> > >  	if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4)
> > >  		return -EINVAL;
> > >  
> > > -	ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
> > > +	ret = of_reserved_mem_region_to_resource(core->dev->of_node, 0, &res);
> > >  	if (ret)
> > >  		return ret;
> > >  
> > >  	mem_phys = res.start;
> > >  	res_size = resource_size(&res);
> > >  
> > > +	ctx_fw = devm_qcom_scm_pas_context_alloc(dev, pas_id, mem_phys, res_size);
> > > +	if (IS_ERR(ctx_fw))
> > > +		return PTR_ERR(ctx_fw);
> > > +
> > >  	ret = request_firmware(&firmware, fw_name, dev);
> > >  	if (ret)
> > >  		return ret;
> > > @@ -52,9 +60,27 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> > >  		goto err_release_fw;
> > >  	}
> > >  
> > > -	ret = qcom_mdt_load(dev, firmware, fw_name,
> > > -			    pas_id, mem_virt, mem_phys, res_size, NULL);
> > > +	ctx_fw->use_tzmem = !!core->dev_fw;
> > > +	ret = qcom_mdt_pas_load(ctx_fw, firmware, fw_name, mem_virt, NULL);
> 
> We need to release the metadata because this is the change compared to
> the previous qcom_mdt_load() API, which silently released DMA memory for
> metadata in the pas_init SCM call for clients that passed metadata ctx
> as NULL. Since with this new API every new client must pass the new pas
> ctx, it cannot be NULL anymore. I intended to document this clearly when
> introducing qcom_mdt_pas_load() API, but I did not do so. but thinking
> it over again, we should not be asking client to release the memory
> which they not allocated, so let me write a patch for this where I
> client like remoteproc explicitly ask or set it if they do not want to
> release this memory as their XPU locked and can only released after auth
> and reset successful.

Just to further clarify, nothing extra related to metadata release need
to done for unaffected client like video who were passing NULL as part
of qcom_mdt_load() earlier., so no changes needed in this patch., I will
basically introduce boolean and set this only for remoteproc clients.


> 
> 
> > > +	if (ret)
> > > +
> > > +	if (ctx_fw->use_tzmem) {
> > > +		domain = iommu_get_domain_for_dev(core->dev_fw);
> > > +		if (!domain) {
> > > +			ret = -ENODEV;
> > > +			goto err_mem_unmap;
> > > +		}
> > > +
> > > +		ret = iommu_map(domain, IRIS_FW_START_ADDR, mem_phys, res_size,
> > > +				IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL);
> > > +		if (ret)
> > > +			goto err_mem_unmap;
> > > +	}
> > >  
> > > +	core->ctx_fw = ctx_fw;
> > > +
> > > +err_mem_unmap:
> > >  	memunmap(mem_virt);
> > >  err_release_fw:
> > >  	release_firmware(firmware);
> > > @@ -62,6 +88,19 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> > >  	return ret;
> > >  }
> > >  
> > > +static void iris_fw_iommu_unmap(struct iris_core *core)
> > > +{
> > > +	bool use_tzmem = core->ctx_fw->use_tzmem;
> > > +	struct iommu_domain *domain;
> > > +
> > > +	if (!use_tzmem)
> > > +		return;
> > > +
> > > +	domain = iommu_get_domain_for_dev(core->dev_fw);
> > > +	if (domain)
> > > +		iommu_unmap(domain, IRIS_FW_START_ADDR, core->ctx_fw->mem_size);
> > > +}
> > > +
> > >  int iris_fw_load(struct iris_core *core)
> > >  {
> > >  	const struct tz_cp_config *cp_config;
> > > @@ -79,10 +118,10 @@ int iris_fw_load(struct iris_core *core)
> > >  		return -ENOMEM;
> > >  	}
> > >  
> > > -	ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id);
> > > +	ret = qcom_scm_pas_prepare_and_auth_reset(core->ctx_fw);
> > >  	if (ret)  {
> > >  		dev_err(core->dev, "auth and reset failed: %d\n", ret);
> > > -		return ret;
> > > +		goto err_unmap;
> > >  	}
> > >  
> > >  	for (i = 0; i < core->iris_platform_data->tz_cp_config_data_size; i++) {
> > > @@ -93,17 +132,31 @@ int iris_fw_load(struct iris_core *core)
> > >  						     cp_config->cp_nonpixel_size);
> > >  		if (ret) {
> > >  			dev_err(core->dev, "qcom_scm_mem_protect_video_var failed: %d\n", ret);
> > > -			qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
> > > -			return ret;
> > > +			goto err_pas_shutdown;
> > >  		}
> > >  	}
> > >  
> > > +	return 0;
> > > +
> > > +err_pas_shutdown:
> > > +	qcom_scm_pas_shutdown(core->ctx_fw->pas_id);
> > > +err_unmap:
> > > +	iris_fw_iommu_unmap(core);
> > > +
> > >  	return ret;
> > >  }
> > >  
> > >  int iris_fw_unload(struct iris_core *core)
> > >  {
> > > -	return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
> > > +	int ret;
> > > +
> > > +	ret = qcom_scm_pas_shutdown(core->ctx_fw->pas_id);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	iris_fw_iommu_unmap(core);
> > > +
> > > +	return ret;
> > >  }
> > >  
> > >  int iris_set_hw_state(struct iris_core *core, bool resume)
> > > 
> > > -- 
> > > 2.34.1
> > > 
> > 
> > -- 
> > -Mukesh Ojha
> 
> -- 
> -Mukesh Ojha

-- 
-Mukesh Ojha

^ permalink raw reply

* Re: [PATCH 05/11] media: iris: Enable Secure PAS support with IOMMU managed by Linux
From: Mukesh Ojha @ 2026-04-15  7:36 UTC (permalink / raw)
  To: Vishnu Reddy
  Cc: Bryan O'Donoghue, Vikash Garodia, Dikshita Agarwal,
	Abhinav Kumar, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Joerg Roedel, Will Deacon,
	Robin Murphy, Bjorn Andersson, Konrad Dybcio, Stefan Schmidt,
	Hans Verkuil, linux-media, linux-arm-msm, devicetree,
	linux-kernel, iommu
In-Reply-To: <20260414063128.6ass64wfi7nmtzti@hu-mojha-hyd.qualcomm.com>

On Tue, Apr 14, 2026 at 12:01:28PM +0530, Mukesh Ojha wrote:
> On Tue, Apr 14, 2026 at 10:30:01AM +0530, Vishnu Reddy wrote:
> > From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> > 
> > Most Qualcomm platforms feature a proprietary hypervisor (such as Gunyah
> > or QHEE), which typically handles IOMMU configuration. This includes
> > mapping memory regions and device memory resources for remote processors
> > by intercepting qcom_scm_pas_auth_and_reset() calls. These mappings are
> > later removed during teardown. Additionally, SHM bridge setup is required
> > to enable memory protection for both remoteproc metadata and its memory
> > regions.
> > 
> > When the hypervisor is absent, the operating system must perform these
> > configurations instead.
> > 
> > Support for handling IOMMU and SHM setup in the absence of a hypervisor
> > is now in place. Extend the Iris driver to enable this functionality on
> > platforms where IOMMU is managed by Linux (i.e., non-Gunyah, non-QHEE).
> > 
> > Additionally, the Iris driver must map the firmware and its required
> > resources to the firmware SID, which is now specified via iommu-map in
> > the device tree.
> > 
> > Co-developed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> > Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
> > Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> > Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
> > ---
> >  drivers/media/platform/qcom/iris/iris_core.h     |  4 ++
> >  drivers/media/platform/qcom/iris/iris_firmware.c | 71 +++++++++++++++++++++---
> >  2 files changed, 66 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
> > index fb194c967ad4..aa7abef6f0e0 100644
> > --- a/drivers/media/platform/qcom/iris/iris_core.h
> > +++ b/drivers/media/platform/qcom/iris/iris_core.h
> > @@ -34,6 +34,8 @@ enum domain_type {
> >   * struct iris_core - holds core parameters valid for all instances
> >   *
> >   * @dev: reference to device structure
> > + * @dev_fw: reference to the context bank device used for firmware load
> > + * @ctx_fw: SCM PAS context for authenticated firmware load and shutdown
> >   * @reg_base: IO memory base address
> >   * @irq: iris irq
> >   * @v4l2_dev: a holder for v4l2 device structure
> > @@ -77,6 +79,8 @@ enum domain_type {
> >  
> >  struct iris_core {
> >  	struct device				*dev;
> > +	struct device				*dev_fw;
> > +	struct qcom_scm_pas_context		*ctx_fw;
> 
> fw_dev suits better and ctx_fw is always for firmware, maybe pas_ctx is
> better.
> 
> >  	void __iomem				*reg_base;
> >  	int					irq;
> >  	struct v4l2_device			v4l2_dev;
> > diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c
> > index 5f408024e967..93d77996c83f 100644
> > --- a/drivers/media/platform/qcom/iris/iris_firmware.c
> > +++ b/drivers/media/platform/qcom/iris/iris_firmware.c
> > @@ -5,6 +5,7 @@
> >  
> >  #include <linux/firmware.h>
> >  #include <linux/firmware/qcom/qcom_scm.h>
> > +#include <linux/iommu.h>
> >  #include <linux/of_address.h>
> >  #include <linux/of_reserved_mem.h>
> >  #include <linux/soc/qcom/mdt_loader.h>
> > @@ -13,12 +14,15 @@
> >  #include "iris_firmware.h"
> >  
> >  #define MAX_FIRMWARE_NAME_SIZE	128
> > +#define IRIS_FW_START_ADDR	0
> >  
> >  static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> >  {
> > +	struct device *dev = core->dev_fw ? core->dev_fw : core->dev;
> >  	u32 pas_id = core->iris_platform_data->pas_id;
> >  	const struct firmware *firmware = NULL;
> > -	struct device *dev = core->dev;
> > +	struct qcom_scm_pas_context *ctx_fw;
> > +	struct iommu_domain *domain;
> >  	struct resource res;
> >  	phys_addr_t mem_phys;
> >  	size_t res_size;
> > @@ -29,13 +33,17 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> >  	if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4)
> >  		return -EINVAL;
> >  
> > -	ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
> > +	ret = of_reserved_mem_region_to_resource(core->dev->of_node, 0, &res);
> >  	if (ret)
> >  		return ret;
> >  
> >  	mem_phys = res.start;
> >  	res_size = resource_size(&res);
> >  
> > +	ctx_fw = devm_qcom_scm_pas_context_alloc(dev, pas_id, mem_phys, res_size);
> > +	if (IS_ERR(ctx_fw))
> > +		return PTR_ERR(ctx_fw);
> > +
> >  	ret = request_firmware(&firmware, fw_name, dev);
> >  	if (ret)
> >  		return ret;
> > @@ -52,9 +60,27 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> >  		goto err_release_fw;
> >  	}
> >  
> > -	ret = qcom_mdt_load(dev, firmware, fw_name,
> > -			    pas_id, mem_virt, mem_phys, res_size, NULL);
> > +	ctx_fw->use_tzmem = !!core->dev_fw;
> > +	ret = qcom_mdt_pas_load(ctx_fw, firmware, fw_name, mem_virt, NULL);

We need to release the metadata because this is the change compared to
the previous qcom_mdt_load() API, which silently released DMA memory for
metadata in the pas_init SCM call for clients that passed metadata ctx
as NULL. Since with this new API every new client must pass the new pas
ctx, it cannot be NULL anymore. I intended to document this clearly when
introducing qcom_mdt_pas_load() API, but I did not do so. but thinking
it over again, we should not be asking client to release the memory
which they not allocated, so let me write a patch for this where I
client like remoteproc explicitly ask or set it if they do not want to
release this memory as their XPU locked and can only released after auth
and reset successful.


> > +	if (ret)
> > +
> > +	if (ctx_fw->use_tzmem) {
> > +		domain = iommu_get_domain_for_dev(core->dev_fw);
> > +		if (!domain) {
> > +			ret = -ENODEV;
> > +			goto err_mem_unmap;
> > +		}
> > +
> > +		ret = iommu_map(domain, IRIS_FW_START_ADDR, mem_phys, res_size,
> > +				IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV, GFP_KERNEL);
> > +		if (ret)
> > +			goto err_mem_unmap;
> > +	}
> >  
> > +	core->ctx_fw = ctx_fw;
> > +
> > +err_mem_unmap:
> >  	memunmap(mem_virt);
> >  err_release_fw:
> >  	release_firmware(firmware);
> > @@ -62,6 +88,19 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> >  	return ret;
> >  }
> >  
> > +static void iris_fw_iommu_unmap(struct iris_core *core)
> > +{
> > +	bool use_tzmem = core->ctx_fw->use_tzmem;
> > +	struct iommu_domain *domain;
> > +
> > +	if (!use_tzmem)
> > +		return;
> > +
> > +	domain = iommu_get_domain_for_dev(core->dev_fw);
> > +	if (domain)
> > +		iommu_unmap(domain, IRIS_FW_START_ADDR, core->ctx_fw->mem_size);
> > +}
> > +
> >  int iris_fw_load(struct iris_core *core)
> >  {
> >  	const struct tz_cp_config *cp_config;
> > @@ -79,10 +118,10 @@ int iris_fw_load(struct iris_core *core)
> >  		return -ENOMEM;
> >  	}
> >  
> > -	ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id);
> > +	ret = qcom_scm_pas_prepare_and_auth_reset(core->ctx_fw);
> >  	if (ret)  {
> >  		dev_err(core->dev, "auth and reset failed: %d\n", ret);
> > -		return ret;
> > +		goto err_unmap;
> >  	}
> >  
> >  	for (i = 0; i < core->iris_platform_data->tz_cp_config_data_size; i++) {
> > @@ -93,17 +132,31 @@ int iris_fw_load(struct iris_core *core)
> >  						     cp_config->cp_nonpixel_size);
> >  		if (ret) {
> >  			dev_err(core->dev, "qcom_scm_mem_protect_video_var failed: %d\n", ret);
> > -			qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
> > -			return ret;
> > +			goto err_pas_shutdown;
> >  		}
> >  	}
> >  
> > +	return 0;
> > +
> > +err_pas_shutdown:
> > +	qcom_scm_pas_shutdown(core->ctx_fw->pas_id);
> > +err_unmap:
> > +	iris_fw_iommu_unmap(core);
> > +
> >  	return ret;
> >  }
> >  
> >  int iris_fw_unload(struct iris_core *core)
> >  {
> > -	return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
> > +	int ret;
> > +
> > +	ret = qcom_scm_pas_shutdown(core->ctx_fw->pas_id);
> > +	if (ret)
> > +		return ret;
> > +
> > +	iris_fw_iommu_unmap(core);
> > +
> > +	return ret;
> >  }
> >  
> >  int iris_set_hw_state(struct iris_core *core, bool resume)
> > 
> > -- 
> > 2.34.1
> > 
> 
> -- 
> -Mukesh Ojha

-- 
-Mukesh Ojha

^ permalink raw reply

* [PATCH v14 5/5] arm64: defconfig: enable Verisilicon IOMMU for Rockchip RK3588
From: Benjamin Gaignard @ 2026-04-15  7:23 UTC (permalink / raw)
  To: joro, will, robin.murphy, krzk+dt, conor+dt, heiko
  Cc: iommu, devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
	kernel, Benjamin Gaignard, Krzysztof Kozlowski
In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com>

Enable Verisilicon IOMMU used by Rockchip RK3588 AV1 hardware codec.
This hardware block could be found in Radxa ROCK 5B board.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index b67d5b1fc45b..b97f5008f6be 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1592,6 +1592,7 @@ CONFIG_ARM_SMMU_V3=y
 CONFIG_MTK_IOMMU=y
 CONFIG_QCOM_IOMMU=y
 CONFIG_APPLE_DART=m
+CONFIG_VSI_IOMMU=m
 CONFIG_REMOTEPROC=y
 CONFIG_IMX_REMOTEPROC=y
 CONFIG_MTK_SCP=m
-- 
2.43.0


^ permalink raw reply related

* [PATCH v14 3/5] iommu: Add verisilicon IOMMU driver
From: Benjamin Gaignard @ 2026-04-15  7:23 UTC (permalink / raw)
  To: joro, will, robin.murphy, krzk+dt, conor+dt, heiko
  Cc: iommu, devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
	kernel, Benjamin Gaignard
In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com>

The Verisilicon IOMMU hardware block can be found in combination
with Verisilicon hardware video codecs (encoders or decoders) on
different SoCs.
Enable it will allow us to use non contiguous memory allocators
for Verisilicon video codecs.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
changes in version 14:
 - Flush TLB after each map/unmap operations.
 - Remove vsi_iommu_restore_ctx() and do not touch Verisilicon stateless
   video decoder.
 - Allow to build the driver as a module.

 MAINTAINERS               |   8 +
 drivers/iommu/Kconfig     |  11 +
 drivers/iommu/Makefile    |   1 +
 drivers/iommu/vsi-iommu.c | 796 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 816 insertions(+)
 create mode 100644 drivers/iommu/vsi-iommu.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c3fe46d7c4bc..fa56dd0e3f25 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27667,6 +27667,14 @@ F:	drivers/media/v4l2-core/v4l2-isp.c
 F:	include/media/v4l2-isp.h
 F:	include/uapi/linux/media/v4l2-isp.h
 
+VERISILICON IOMMU DRIVER
+M:	Benjamin Gaignard <benjamin.gaignard@collabora.com>
+L:	iommu@lists.linux.dev
+S:	Maintained
+F:	Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
+F:	drivers/iommu/vsi-iommu.c
+F:	include/linux/vsi-iommu.h
+
 VF610 NAND DRIVER
 M:	Stefan Agner <stefan@agner.ch>
 L:	linux-mtd@lists.infradead.org
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f86262b11416..18d3d68af7cd 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -384,6 +384,17 @@ config SPRD_IOMMU
 
 	  Say Y here if you want to use the multimedia devices listed above.
 
+config VSI_IOMMU
+	tristate "Verisilicon IOMMU Support"
+	depends on (ARCH_ROCKCHIP && ARM64) || COMPILE_TEST
+	select IOMMU_API
+	help
+	  Support for IOMMUs used by Verisilicon sub-systems like video
+	  decoders or encoder hardware blocks.
+
+	  Say Y here if you want to use this IOMMU in front of these
+	  hardware blocks.
+
 config IOMMU_DEBUG_PAGEALLOC
 	bool "Debug IOMMU mappings against page allocations"
 	depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 0275821f4ef9..887af357a7c9 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -36,4 +36,5 @@ obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o
 obj-$(CONFIG_IOMMU_IOPF) += io-pgfault.o
 obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
 obj-$(CONFIG_APPLE_DART) += apple-dart.o
+obj-$(CONFIG_VSI_IOMMU) += vsi-iommu.o
 obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) += iommu-debug-pagealloc.o
diff --git a/drivers/iommu/vsi-iommu.c b/drivers/iommu/vsi-iommu.c
new file mode 100644
index 000000000000..5d0721bd2c7a
--- /dev/null
+++ b/drivers/iommu/vsi-iommu.c
@@ -0,0 +1,796 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2025 Collabora Ltd.
+ *
+ * IOMMU API for Verisilicon
+ *
+ * Module Authors:	Yandong Lin <yandong.lin@rock-chips.com>
+ *			Simon Xue <xxm@rock-chips.com>
+ *			Benjamin Gaignard <benjamin.gaignard@collabora.com>
+ *
+ * This hardware block is using a 2 pages tables allocation structure.
+ * That make very similar to Rockhip iommu hardware blocks but it has
+ * it own driver because the registers offset and configuration bits
+ * are completely different. An additional reason is that this hardware
+ * has been developed by Verisilicon to be used by their hardware video
+ * decoders and not for a general purpose like Rockchip iommus.
+ */
+
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_iommu.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "iommu-pages.h"
+
+struct vsi_iommu {
+	struct device *dev;
+	void __iomem *regs;
+	struct clk_bulk_data *clocks;
+	int num_clocks;
+	struct iommu_device iommu;
+	struct list_head node; /* entry in vsi_iommu_domain.iommus */
+	struct iommu_domain *domain; /* domain to which iommu is attached */
+	spinlock_t lock; /* lock to protect vsi_iommu fields */
+	int irq;
+	bool enable;
+};
+
+struct vsi_iommu_domain {
+	struct list_head iommus;
+	struct device *dev;
+	u32 *dt;
+	dma_addr_t dt_dma;
+	struct iommu_domain domain;
+	u64 *pta;
+	dma_addr_t pta_dma;
+	spinlock_t lock; /* lock to protect vsi_iommu_domain fields */
+};
+
+static struct iommu_domain vsi_identity_domain;
+
+#define NUM_DT_ENTRIES	1024
+#define NUM_PT_ENTRIES	1024
+
+#define SPAGE_SIZE	BIT(12)
+
+/* vsi iommu regs address */
+#define VSI_MMU_CONFIG1_BASE			0x1ac
+#define VSI_MMU_AHB_EXCEPTION_BASE		0x380
+#define VSI_MMU_AHB_CONTROL_BASE		0x388
+#define VSI_MMU_AHB_TLB_ARRAY_BASE_L_BASE	0x38C
+
+/* MMU register offsets */
+#define VSI_MMU_FLUSH_BASE		0x184
+#define VSI_MMU_BIT_FLUSH		BIT(4)
+
+#define VSI_MMU_PAGE_FAULT_ADDR		0x380
+#define VSI_MMU_STATUS_BASE		0x384	/* IRQ status */
+
+#define VSI_MMU_BIT_ENABLE		BIT(0)
+
+#define VSI_MMU_OUT_OF_BOUND		BIT(28)
+/* Irq mask */
+#define VSI_MMU_IRQ_MASK		0x7
+
+#define VSI_DTE_PT_ADDRESS_MASK		0xffffffc0
+#define VSI_DTE_PT_VALID		BIT(0)
+
+#define VSI_PAGE_DESC_LO_MASK		0xfffff000
+#define VSI_PAGE_DESC_HI_MASK		GENMASK_ULL(39, 32)
+#define VSI_PAGE_DESC_HI_SHIFT		(32 - 4)
+
+static inline phys_addr_t vsi_dte_pt_address(u32 dte)
+{
+	return (phys_addr_t)dte & VSI_DTE_PT_ADDRESS_MASK;
+}
+
+static inline u32 vsi_mk_dte(u32 dte)
+{
+	return (phys_addr_t)dte | VSI_DTE_PT_VALID;
+}
+
+#define VSI_PTE_PAGE_WRITABLE		BIT(2)
+#define VSI_PTE_PAGE_VALID		BIT(0)
+
+static inline phys_addr_t vsi_pte_page_address(u64 pte)
+{
+	return ((pte << VSI_PAGE_DESC_HI_SHIFT) & VSI_PAGE_DESC_HI_MASK) |
+	       (pte & VSI_PAGE_DESC_LO_MASK);
+}
+
+static u32 vsi_mk_pte(phys_addr_t page, int prot)
+{
+	u32 flags = 0;
+
+	flags |= (prot & IOMMU_WRITE) ? VSI_PTE_PAGE_WRITABLE : 0;
+
+	page = (page & VSI_PAGE_DESC_LO_MASK) |
+	       ((page & VSI_PAGE_DESC_HI_MASK) >> VSI_PAGE_DESC_HI_SHIFT);
+
+	return page | flags | VSI_PTE_PAGE_VALID;
+}
+
+#define VSI_DTE_PT_VALID	BIT(0)
+
+static inline bool vsi_dte_is_pt_valid(u32 dte)
+{
+	return dte & VSI_DTE_PT_VALID;
+}
+
+static inline bool vsi_pte_is_page_valid(u32 pte)
+{
+	return pte & VSI_PTE_PAGE_VALID;
+}
+
+static u32 vsi_mk_pte_invalid(u32 pte)
+{
+	return pte & ~VSI_PTE_PAGE_VALID;
+}
+
+#define VSI_MASTER_TLB_MASK	GENMASK_ULL(31, 10)
+/* mode 0 : 4k */
+#define VSI_PTA_4K_MODE	0
+
+static u64 vsi_mk_pta(dma_addr_t dt_dma)
+{
+	u64 val = (dt_dma & VSI_MASTER_TLB_MASK) | VSI_PTA_4K_MODE;
+
+	return val;
+}
+
+static struct vsi_iommu_domain *to_vsi_domain(struct iommu_domain *dom)
+{
+	return container_of(dom, struct vsi_iommu_domain, domain);
+}
+
+static inline void vsi_table_flush(struct vsi_iommu_domain *vsi_domain, dma_addr_t dma,
+				   unsigned int count)
+{
+	size_t size = count * sizeof(u32); /* count of u32 entry */
+
+	dma_sync_single_for_device(vsi_domain->dev, dma, size, DMA_TO_DEVICE);
+}
+
+#define VSI_IOVA_DTE_MASK	0xffc00000
+#define VSI_IOVA_DTE_SHIFT	22
+#define VSI_IOVA_PTE_MASK	0x003ff000
+#define VSI_IOVA_PTE_SHIFT	12
+#define VSI_IOVA_PAGE_MASK	0x00000fff
+#define VSI_IOVA_PAGE_SHIFT	0
+
+static u32 vsi_iova_dte_index(u32 iova)
+{
+	return (iova & VSI_IOVA_DTE_MASK) >> VSI_IOVA_DTE_SHIFT;
+}
+
+static u32 vsi_iova_pte_index(u32 iova)
+{
+	return (iova & VSI_IOVA_PTE_MASK) >> VSI_IOVA_PTE_SHIFT;
+}
+
+static u32 vsi_iova_page_offset(u32 iova)
+{
+	return (iova & VSI_IOVA_PAGE_MASK) >> VSI_IOVA_PAGE_SHIFT;
+}
+
+static irqreturn_t vsi_iommu_irq(int irq, void *dev_id)
+{
+	struct vsi_iommu *iommu = dev_id;
+	unsigned long flags;
+	dma_addr_t iova;
+	u32 status;
+
+	if (pm_runtime_resume_and_get(iommu->dev) < 0)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	status = readl(iommu->regs + VSI_MMU_STATUS_BASE);
+	if (status & VSI_MMU_IRQ_MASK) {
+		dev_err(iommu->dev, "unexpected int_status=%08x\n", status);
+		iova = readl(iommu->regs + VSI_MMU_PAGE_FAULT_ADDR);
+		report_iommu_fault(iommu->domain, iommu->dev, iova, status);
+	}
+	writel(0, iommu->regs + VSI_MMU_STATUS_BASE);
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+	pm_runtime_put_autosuspend(iommu->dev);
+
+	return IRQ_HANDLED;
+}
+
+static struct vsi_iommu *vsi_iommu_get_from_dev(struct device *dev)
+{
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+	struct device *iommu_dev = bus_find_device_by_fwnode(&platform_bus_type,
+							     fwspec->iommu_fwnode);
+
+	put_device(iommu_dev);
+
+	return iommu_dev ? dev_get_drvdata(iommu_dev) : NULL;
+}
+
+static struct iommu_domain *vsi_iommu_domain_alloc_paging(struct device *dev)
+{
+	struct vsi_iommu *iommu = dev_iommu_priv_get(dev);
+	struct vsi_iommu_domain *vsi_domain;
+
+	vsi_domain = kzalloc(sizeof(*vsi_domain), GFP_KERNEL);
+	if (!vsi_domain)
+		return NULL;
+
+	vsi_domain->dev = iommu->dev;
+	spin_lock_init(&vsi_domain->lock);
+
+	/*
+	 * iommu use a 2 level pagetable.
+	 * Each level1 (dt) and level2 (pt) table has 1024 4-byte entries.
+	 * Allocate one 4 KiB page for each table.
+	 */
+	vsi_domain->dt = iommu_alloc_pages_sz(GFP_KERNEL | GFP_DMA32,
+					      SPAGE_SIZE);
+	if (!vsi_domain->dt)
+		goto err_free_domain;
+
+	vsi_domain->dt_dma = dma_map_single(vsi_domain->dev, vsi_domain->dt,
+					    SPAGE_SIZE, DMA_TO_DEVICE);
+	if (dma_mapping_error(vsi_domain->dev, vsi_domain->dt_dma)) {
+		dev_err(dev, "DMA map error for DT\n");
+		goto err_free_dt;
+	}
+
+	vsi_domain->pta = iommu_alloc_pages_sz(GFP_KERNEL | GFP_DMA32,
+					       SPAGE_SIZE);
+	if (!vsi_domain->pta)
+		goto err_unmap_dt;
+
+	vsi_domain->pta[0] = vsi_mk_pta(vsi_domain->dt_dma);
+	vsi_domain->pta_dma = dma_map_single(vsi_domain->dev, vsi_domain->pta,
+					     SPAGE_SIZE, DMA_TO_DEVICE);
+	if (dma_mapping_error(vsi_domain->dev, vsi_domain->pta_dma)) {
+		dev_err(dev, "DMA map error for PTA\n");
+		goto err_free_pta;
+	}
+
+	INIT_LIST_HEAD(&vsi_domain->iommus);
+
+	vsi_domain->domain.geometry.aperture_start = 0;
+	vsi_domain->domain.geometry.aperture_end   = DMA_BIT_MASK(32);
+	vsi_domain->domain.geometry.force_aperture = true;
+	vsi_domain->domain.pgsize_bitmap	   = SZ_4K;
+
+	return &vsi_domain->domain;
+
+err_free_pta:
+	iommu_free_pages(vsi_domain->pta);
+err_unmap_dt:
+	dma_unmap_single(vsi_domain->dev, vsi_domain->dt_dma,
+			 SPAGE_SIZE, DMA_TO_DEVICE);
+err_free_dt:
+	iommu_free_pages(vsi_domain->dt);
+err_free_domain:
+	kfree(vsi_domain);
+
+	return NULL;
+}
+
+static phys_addr_t vsi_iommu_iova_to_phys(struct iommu_domain *domain,
+					  dma_addr_t iova)
+{
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	phys_addr_t pt_phys, phys = 0;
+	unsigned long flags;
+	u32 dte, pte;
+	u32 *page_table;
+
+	spin_lock_irqsave(&vsi_domain->lock, flags);
+	dte = vsi_domain->dt[vsi_iova_dte_index(iova)];
+	if (!vsi_dte_is_pt_valid(dte))
+		goto unlock;
+
+	pt_phys = vsi_dte_pt_address(dte);
+	page_table = (u32 *)phys_to_virt(pt_phys);
+	pte = page_table[vsi_iova_pte_index(iova)];
+	if (!vsi_pte_is_page_valid(pte))
+		goto unlock;
+
+	phys = vsi_pte_page_address(pte) + vsi_iova_page_offset(iova);
+
+unlock:
+	spin_unlock_irqrestore(&vsi_domain->lock, flags);
+	return phys;
+}
+
+static size_t vsi_iommu_unmap_iova(struct vsi_iommu_domain *vsi_domain,
+				   u32 *pte_addr, dma_addr_t pte_dma,
+				   size_t size)
+{
+	unsigned int pte_count;
+	unsigned int pte_total = size / SPAGE_SIZE;
+
+	for (pte_count = 0;
+	     pte_count < pte_total && pte_count < NUM_PT_ENTRIES; pte_count++) {
+		u32 pte = pte_addr[pte_count];
+
+		if (!vsi_pte_is_page_valid(pte))
+			break;
+
+		pte_addr[pte_count] = vsi_mk_pte_invalid(pte);
+	}
+
+	vsi_table_flush(vsi_domain, pte_dma, pte_total);
+
+	return pte_count * SPAGE_SIZE;
+}
+
+static int vsi_iommu_map_iova(struct vsi_iommu_domain *vsi_domain, u32 *pte_addr,
+			      dma_addr_t pte_dma, dma_addr_t iova,
+			      phys_addr_t paddr, size_t size, int prot)
+{
+	unsigned int pte_count;
+	unsigned int pte_total = size / SPAGE_SIZE;
+
+	for (pte_count = 0;
+	     pte_count < pte_total && pte_count < NUM_PT_ENTRIES; pte_count++) {
+		u32 pte = pte_addr[pte_count];
+
+		if (vsi_pte_is_page_valid(pte))
+			return (pte_count - 1) * SPAGE_SIZE;
+
+		pte_addr[pte_count] = vsi_mk_pte(paddr, prot);
+
+		paddr += SPAGE_SIZE;
+	}
+
+	vsi_table_flush(vsi_domain, pte_dma, pte_total);
+
+	return 0;
+}
+
+static void vsi_iommu_flush_tlb(struct iommu_domain *domain)
+{
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	struct list_head *pos;
+
+	list_for_each(pos, &vsi_domain->iommus) {
+		struct vsi_iommu *iommu;
+
+		iommu = list_entry(pos, struct vsi_iommu, node);
+		if (!iommu)
+			continue;
+
+		if (pm_runtime_get(iommu->dev) < 0)
+			continue;
+
+		spin_lock(&iommu->lock);
+
+		if (iommu->enable) {
+			writel(VSI_MMU_BIT_FLUSH, iommu->regs + VSI_MMU_FLUSH_BASE);
+			writel(0, iommu->regs + VSI_MMU_FLUSH_BASE);
+		}
+
+		spin_unlock(&iommu->lock);
+
+		pm_runtime_put_autosuspend(iommu->dev);
+	}
+}
+
+static size_t vsi_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
+			      size_t size, size_t count, struct iommu_iotlb_gather *gather)
+{
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	dma_addr_t pte_dma, iova = (dma_addr_t)_iova;
+	unsigned long flags;
+	phys_addr_t pt_phys;
+	u32 dte;
+	u32 *pte_addr;
+	size_t unmap_size = 0;
+
+	spin_lock_irqsave(&vsi_domain->lock, flags);
+
+	dte = vsi_domain->dt[vsi_iova_dte_index(iova)];
+	/* Just return 0 if iova is unmapped */
+	if (!vsi_dte_is_pt_valid(dte))
+		goto unlock;
+
+	pt_phys = vsi_dte_pt_address(dte);
+	pte_addr = (u32 *)phys_to_virt(pt_phys) + vsi_iova_pte_index(iova);
+	pte_dma = pt_phys + vsi_iova_pte_index(iova) * sizeof(u32);
+	unmap_size = vsi_iommu_unmap_iova(vsi_domain, pte_addr, pte_dma, size);
+	if (!unmap_size)
+		goto unlock;
+
+	vsi_iommu_flush_tlb(domain);
+unlock:
+	spin_unlock_irqrestore(&vsi_domain->lock, flags);
+
+	return unmap_size;
+}
+
+static u32 *vsi_dte_get_page_table(struct vsi_iommu_domain *vsi_domain,
+				   dma_addr_t iova, gfp_t gfp)
+{
+	u32 *page_table, *dte_addr;
+	u32 dte_index, dte;
+	phys_addr_t pt_phys;
+	dma_addr_t pt_dma;
+	gfp_t flags;
+
+	dte_index = vsi_iova_dte_index(iova);
+	dte_addr = &vsi_domain->dt[dte_index];
+	dte = *dte_addr;
+	if (vsi_dte_is_pt_valid(dte))
+		goto done;
+
+	/* Do not allow to sleep while allocating the buffer */
+	flags = (gfp & ~GFP_KERNEL) | GFP_ATOMIC | GFP_DMA32;
+	page_table = iommu_alloc_pages_sz(flags, PAGE_SIZE);
+	if (!page_table)
+		return ERR_PTR(-ENOMEM);
+
+	pt_dma = dma_map_single(vsi_domain->dev, page_table, PAGE_SIZE, DMA_TO_DEVICE);
+	if (dma_mapping_error(vsi_domain->dev, pt_dma)) {
+		dev_err(vsi_domain->dev, "DMA mapping error while allocating page table\n");
+		iommu_free_pages(page_table);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dte = vsi_mk_dte(pt_dma);
+	*dte_addr = dte;
+
+	vsi_table_flush(vsi_domain,
+			vsi_domain->dt_dma + dte_index * sizeof(u32), 1);
+done:
+	pt_phys = vsi_dte_pt_address(dte);
+	return (u32 *)phys_to_virt(pt_phys);
+}
+
+static int vsi_iommu_map(struct iommu_domain *domain, unsigned long _iova,
+			 phys_addr_t paddr, size_t size, size_t count,
+			 int prot, gfp_t gfp, size_t *mapped)
+{
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	dma_addr_t pte_dma, iova = (dma_addr_t)_iova;
+	u32 *page_table, *pte_addr;
+	u32 dte, pte_index;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&vsi_domain->lock, flags);
+
+	page_table = vsi_dte_get_page_table(vsi_domain, iova, gfp);
+	if (IS_ERR(page_table)) {
+		spin_unlock_irqrestore(&vsi_domain->lock, flags);
+		return PTR_ERR(page_table);
+	}
+
+	dte = vsi_domain->dt[vsi_iova_dte_index(iova)];
+	pte_index = vsi_iova_pte_index(iova);
+	pte_addr = &page_table[pte_index];
+	pte_dma = vsi_dte_pt_address(dte) + pte_index * sizeof(u32);
+	ret = vsi_iommu_map_iova(vsi_domain, pte_addr, pte_dma, iova,
+				 paddr, size, prot);
+	if (!ret)
+		*mapped = size;
+
+	vsi_iommu_flush_tlb(domain);
+
+	spin_unlock_irqrestore(&vsi_domain->lock, flags);
+
+	return ret;
+}
+
+static void vsi_iommu_disable(struct vsi_iommu *iommu)
+{
+	writel(0, iommu->regs + VSI_MMU_AHB_CONTROL_BASE);
+	iommu->enable = false;
+}
+
+static int vsi_iommu_identity_attach(struct iommu_domain *domain,
+				     struct device *dev, struct iommu_domain *old)
+{
+	struct vsi_iommu *iommu = dev_iommu_priv_get(dev);
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	unsigned long flags;
+	int ret;
+
+	ret = pm_runtime_resume_and_get(iommu->dev);
+	if (ret < 0)
+		return ret;
+
+	spin_lock_irqsave(&vsi_domain->lock, flags);
+	spin_lock(&iommu->lock);
+	if (iommu->domain == domain)
+		goto unlock;
+
+	vsi_iommu_disable(iommu);
+	list_del_init(&iommu->node);
+
+	iommu->domain = domain;
+
+unlock:
+	spin_unlock(&iommu->lock);
+	spin_unlock_irqrestore(&vsi_domain->lock, flags);
+	pm_runtime_put_autosuspend(iommu->dev);
+	return 0;
+}
+
+static const struct iommu_domain_ops vsi_identity_ops = {
+	.attach_dev = vsi_iommu_identity_attach,
+};
+
+static struct iommu_domain vsi_identity_domain = {
+	.type = IOMMU_DOMAIN_IDENTITY,
+	.ops = &vsi_identity_ops,
+};
+
+static void vsi_iommu_enable(struct vsi_iommu *iommu, struct iommu_domain *domain)
+{
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+
+	if (domain == &vsi_identity_domain)
+		return;
+
+	writel(vsi_domain->pta_dma, iommu->regs + VSI_MMU_AHB_TLB_ARRAY_BASE_L_BASE);
+	writel(VSI_MMU_OUT_OF_BOUND, iommu->regs + VSI_MMU_CONFIG1_BASE);
+	writel(VSI_MMU_BIT_ENABLE, iommu->regs + VSI_MMU_AHB_EXCEPTION_BASE);
+	writel(VSI_MMU_BIT_ENABLE, iommu->regs + VSI_MMU_AHB_CONTROL_BASE);
+	iommu->enable = true;
+}
+
+static int vsi_iommu_attach_device(struct iommu_domain *domain,
+				   struct device *dev, struct iommu_domain *old)
+{
+	struct vsi_iommu *iommu = dev_iommu_priv_get(dev);
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	unsigned long flags;
+	int ret = 0;
+
+	ret = pm_runtime_resume_and_get(iommu->dev);
+	if (ret < 0)
+		return ret;
+
+	spin_lock_irqsave(&vsi_domain->lock, flags);
+	spin_lock(&iommu->lock);
+
+	vsi_iommu_enable(iommu, domain);
+	writel(VSI_MMU_BIT_FLUSH, iommu->regs + VSI_MMU_FLUSH_BASE);
+	writel(0, iommu->regs + VSI_MMU_FLUSH_BASE);
+
+	list_del_init(&iommu->node);
+	list_add_tail(&iommu->node, &vsi_domain->iommus);
+
+	iommu->domain = domain;
+
+	spin_unlock(&iommu->lock);
+	spin_unlock_irqrestore(&vsi_domain->lock, flags);
+	pm_runtime_put_autosuspend(iommu->dev);
+	return ret;
+}
+
+static void vsi_iommu_domain_free(struct iommu_domain *domain)
+{
+	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&vsi_domain->lock, flags);
+
+	WARN_ON(!list_empty(&vsi_domain->iommus));
+
+	for (i = 0; i < NUM_DT_ENTRIES; i++) {
+		u32 dte = vsi_domain->dt[i];
+
+		if (vsi_dte_is_pt_valid(dte)) {
+			phys_addr_t pt_phys = vsi_dte_pt_address(dte);
+			u32 *page_table = phys_to_virt(pt_phys);
+
+			dma_unmap_single(vsi_domain->dev, pt_phys,
+					 SPAGE_SIZE, DMA_TO_DEVICE);
+			iommu_free_pages(page_table);
+		}
+	}
+
+	dma_unmap_single(vsi_domain->dev, vsi_domain->dt_dma,
+			 SPAGE_SIZE, DMA_TO_DEVICE);
+	iommu_free_pages(vsi_domain->dt);
+
+	dma_unmap_single(vsi_domain->dev, vsi_domain->pta_dma,
+			 SPAGE_SIZE, DMA_TO_DEVICE);
+	iommu_free_pages(vsi_domain->pta);
+
+	spin_unlock_irqrestore(&vsi_domain->lock, flags);
+
+	kfree(vsi_domain);
+}
+
+static struct iommu_device *vsi_iommu_probe_device(struct device *dev)
+{
+	struct vsi_iommu *iommu = vsi_iommu_get_from_dev(dev);
+	struct device_link *link;
+
+	link = device_link_add(dev, iommu->dev,
+			       DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
+	if (!link)
+		dev_err(dev, "Unable to link %s\n", dev_name(iommu->dev));
+
+	dev_iommu_priv_set(dev, iommu);
+	return &iommu->iommu;
+}
+
+static void vsi_iommu_release_device(struct device *dev)
+{
+	struct vsi_iommu *iommu = dev_iommu_priv_get(dev);
+
+	device_link_remove(dev, iommu->dev);
+}
+
+static int vsi_iommu_of_xlate(struct device *dev, const struct of_phandle_args *args)
+{
+	return iommu_fwspec_add_ids(dev, args->args, 1);
+}
+
+static const struct iommu_ops vsi_iommu_ops = {
+	.identity_domain = &vsi_identity_domain,
+	.release_domain = &vsi_identity_domain,
+	.domain_alloc_paging = vsi_iommu_domain_alloc_paging,
+	.of_xlate = vsi_iommu_of_xlate,
+	.probe_device = vsi_iommu_probe_device,
+	.release_device = vsi_iommu_release_device,
+	.device_group = generic_single_device_group,
+	.owner = THIS_MODULE,
+	.default_domain_ops = &(const struct iommu_domain_ops) {
+		.attach_dev		= vsi_iommu_attach_device,
+		.map_pages		= vsi_iommu_map,
+		.unmap_pages		= vsi_iommu_unmap,
+		.iova_to_phys		= vsi_iommu_iova_to_phys,
+		.free			= vsi_iommu_domain_free,
+	}
+};
+
+static const struct of_device_id vsi_iommu_dt_ids[] = {
+	{
+		.compatible = "verisilicon,iommu-1.2",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vsi_iommu_dt_ids);
+
+static int vsi_iommu_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct vsi_iommu *iommu;
+	int err;
+
+	iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENOMEM;
+
+	iommu->dev = dev;
+	spin_lock_init(&iommu->lock);
+	INIT_LIST_HEAD(&iommu->node);
+
+	iommu->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(iommu->regs))
+		return -ENOMEM;
+
+	iommu->num_clocks = devm_clk_bulk_get_all(dev, &iommu->clocks);
+	if  (iommu->num_clocks < 0)
+		return iommu->num_clocks;
+
+	err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
+	if (err)
+		return err;
+
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0)
+		return iommu->irq;
+
+	err = devm_request_irq(iommu->dev, iommu->irq, vsi_iommu_irq,
+			       IRQF_SHARED, dev_name(dev), iommu);
+	if (err)
+		goto err_unprepare_clocks;
+
+	dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+	platform_set_drvdata(pdev, iommu);
+
+	pm_runtime_set_autosuspend_delay(dev, 100);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_enable(dev);
+
+	err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+	if (err)
+		goto err_runtime_disable;
+
+	err = iommu_device_register(&iommu->iommu, &vsi_iommu_ops, dev);
+	if (err)
+		goto err_remove_sysfs;
+
+	return 0;
+
+err_remove_sysfs:
+	iommu_device_sysfs_remove(&iommu->iommu);
+err_runtime_disable:
+	pm_runtime_disable(dev);
+err_unprepare_clocks:
+	clk_bulk_unprepare(iommu->num_clocks, iommu->clocks);
+	return err;
+}
+
+static void vsi_iommu_shutdown(struct platform_device *pdev)
+{
+	struct vsi_iommu *iommu = platform_get_drvdata(pdev);
+
+	disable_irq(iommu->irq);
+	pm_runtime_force_suspend(&pdev->dev);
+}
+
+static int __maybe_unused vsi_iommu_suspend(struct device *dev)
+{
+	struct vsi_iommu *iommu = dev_get_drvdata(dev);
+
+	vsi_iommu_disable(iommu);
+
+	clk_bulk_disable(iommu->num_clocks, iommu->clocks);
+
+	return 0;
+}
+
+static int __maybe_unused vsi_iommu_resume(struct device *dev)
+{
+	struct vsi_iommu *iommu = dev_get_drvdata(dev);
+	unsigned long flags;
+	int ret;
+
+	ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
+	if (ret)
+		return ret;
+
+	if (iommu->domain) {
+		struct vsi_iommu_domain *vsi_domain = to_vsi_domain(iommu->domain);
+
+		spin_lock_irqsave(&vsi_domain->lock, flags);
+		spin_lock(&iommu->lock);
+		vsi_iommu_enable(iommu, iommu->domain);
+		spin_unlock(&iommu->lock);
+		spin_unlock_irqrestore(&vsi_domain->lock, flags);
+	}
+
+	return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(vsi_iommu_pm_ops,
+				 vsi_iommu_suspend, vsi_iommu_resume,
+				 NULL);
+
+static struct platform_driver rockchip_vsi_iommu_driver = {
+	.probe = vsi_iommu_probe,
+	.shutdown = vsi_iommu_shutdown,
+	.driver = {
+		   .name = "vsi_iommu",
+		   .of_match_table = vsi_iommu_dt_ids,
+		   .pm = pm_sleep_ptr(&vsi_iommu_pm_ops),
+		   .suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(rockchip_vsi_iommu_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@collabora.com>");
+MODULE_DESCRIPTION("Verisilicon IOMMU driver");
-- 
2.43.0


^ permalink raw reply related

* [PATCH v14 4/5] arm64: dts: rockchip: Add verisilicon IOMMU node on RK3588
From: Benjamin Gaignard @ 2026-04-15  7:23 UTC (permalink / raw)
  To: joro, will, robin.murphy, krzk+dt, conor+dt, heiko
  Cc: iommu, devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
	kernel, Benjamin Gaignard
In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com>

Add the device tree node for the Verisilicon IOMMU present
in the RK3588 SoC.
This IOMMU handles address translation for the VPU hardware blocks.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
index 7fe9593d8c19..7fde18feeaf8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
@@ -1428,6 +1428,17 @@ av1d: video-codec@fdc70000 {
 		clock-names = "aclk", "hclk";
 		power-domains = <&power RK3588_PD_AV1>;
 		resets = <&cru SRST_A_AV1>, <&cru SRST_P_AV1>, <&cru SRST_A_AV1_BIU>, <&cru SRST_P_AV1_BIU>;
+		iommus = <&av1d_mmu>;
+	};
+
+	av1d_mmu: iommu@fdca0000 {
+		compatible = "rockchip,rk3588-av1-iommu", "verisilicon,iommu-1.2";
+		reg = <0x0 0xfdca0000 0x0 0x600>;
+		interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>;
+		clocks = <&cru ACLK_AV1>, <&cru PCLK_AV1>;
+		clock-names = "core", "iface";
+		#iommu-cells = <0>;
+		power-domains = <&power RK3588_PD_AV1>;
 	};
 
 	vop: vop@fdd90000 {
-- 
2.43.0


^ permalink raw reply related


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