* 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
* [PATCH v14 2/5] dt-bindings: iommu: verisilicon: Add binding for VSI IOMMU
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, Conor Dooley
In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com>
Add a device tree binding for the Verisilicon (VSI) IOMMU.
This IOMMU sits in front of hardware encoder and decoder
blocks on SoCs using Verisilicon IP, such as the Rockchip RK3588.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/iommu/verisilicon,iommu.yaml | 71 +++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
diff --git a/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml b/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
new file mode 100644
index 000000000000..d3ce9e603b61
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iommu/verisilicon,iommu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Verisilicon IOMMU
+
+maintainers:
+ - Benjamin Gaignard <benjamin.gaignard@collabora.com>
+
+description: |+
+ A Versilicon iommu translates io virtual addresses to physical addresses for
+ its associated video decoder.
+
+properties:
+ compatible:
+ items:
+ - const: rockchip,rk3588-av1-iommu
+ - const: verisilicon,iommu-1.2
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Core clock
+ - description: Interface clock
+
+ clock-names:
+ items:
+ - const: core
+ - const: iface
+
+ "#iommu-cells":
+ const: 0
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - "#iommu-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ 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>;
+ };
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v14 1/5] dt-bindings: vendor-prefixes: Add Verisilicon
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, Conor Dooley
In-Reply-To: <20260415072349.44237-1-benjamin.gaignard@collabora.com>
Verisilicon Microelectronics is a company based in Shanghai, China,
developping hardware blocks for SoC.
https://verisilicon.com/
Add their name to the list of vendors.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index ee7fd3cfe203..ebd9072300a8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1761,6 +1761,8 @@ patternProperties:
description: Variscite Ltd.
"^vdl,.*":
description: Van der Laan b.v.
+ "^verisilicon,.*":
+ description: VeriSilicon Microelectronics
"^vertexcom,.*":
description: Vertexcom Technologies, Inc.
"^via,.*":
--
2.43.0
^ permalink raw reply related
* [PATCH v14 0/5] Add support for Verisilicon IOMMU used by media codec blocks
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
Hi all,
This patch series adds support for the Verisilicon IOMMU, which is found in front
of hardware encoder and decoder blocks in several SoCs using Verisilicon IP.
A first implementation of this IOMMU is available on the Rockchip RK3588 SoC.
Rockchip provides a driver for this hardware in their 6.1 kernel branch:
https://github.com/rockchip-linux/kernel/blob/develop-6.1/drivers/iommu/rockchip-iommu-av1d.c
This series includes:
- a new binding for the Verisilicon IOMMU
- a driver implementation
- DT updates for RK3588
The driver was forward-ported from Rockchip’s 6.1 implementation,
the prefix was renamed to vsi for generality, and several fixes were
applied.
AV1 decoding was tested using the stateless VPU driver and Fluster.
The test results show a score of 205/239, which confirms that no
regressions were introduced by this series.
Feedback and testing welcome.
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.
changes in version 13:
- On top the driver file explicit why the hardware is different than Rockchip IOMMU
- Document why vsi_iommu_restore_ctx() is needed when using Verisilicon
stateless video decoder.
changes in version 12:
- Remove useless vsi_iommu_flush_tlb_all()
- Merge MAINTAINERS changes in the patch introducing VSI iommu driver
Benjamin Gaignard (5):
dt-bindings: vendor-prefixes: Add Verisilicon
dt-bindings: iommu: verisilicon: Add binding for VSI IOMMU
iommu: Add verisilicon IOMMU driver
arm64: dts: rockchip: Add verisilicon IOMMU node on RK3588
arm64: defconfig: enable Verisilicon IOMMU for Rockchip RK3588
.../bindings/iommu/verisilicon,iommu.yaml | 71 ++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
MAINTAINERS | 8 +
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 11 +
arch/arm64/configs/defconfig | 1 +
drivers/iommu/Kconfig | 11 +
drivers/iommu/Makefile | 1 +
drivers/iommu/vsi-iommu.c | 796 ++++++++++++++++++
8 files changed, 901 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iommu/verisilicon,iommu.yaml
create mode 100644 drivers/iommu/vsi-iommu.c
--
2.43.0
^ permalink raw reply
* [PATCH v3 3/3] PCI: ultrarisc: Add UltraRISC DP1000 PCIe Root Complex driver
From: Jia Wang @ 2026-04-15 7:21 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Jingoo Han,
Xincheng Zhang, Krzysztof Kozlowski, Conor Dooley
Cc: linux-riscv, linux-kernel, linux-pci, devicetree, Jia Wang
In-Reply-To: <20260415-ultrarisc-pcie-v3-0-73f06e972616@ultrarisc.com>
From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
Add DP1000 SoC PCIe Root Complex driver.
Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
MAINTAINERS | 1 +
drivers/pci/controller/dwc/Kconfig | 12 ++
drivers/pci/controller/dwc/Makefile | 1 +
drivers/pci/controller/dwc/pcie-designware.h | 22 ++++
drivers/pci/controller/dwc/pcie-ultrarisc.c | 186 +++++++++++++++++++++++++++
5 files changed, 222 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2ec02d8443dd..c8159670a14d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20588,6 +20588,7 @@ M: Jia Wang <wangjia@ultrarisc.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/ultrarisc,dp1000-pcie.yaml
+F: drivers/pci/controller/dwc/pcie-ultrarisc.c
PCIE ENDPOINT DRIVER FOR QUALCOMM
M: Manivannan Sadhasivam <mani@kernel.org>
diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index d0aa031397fa..06f7d98259cd 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -548,4 +548,16 @@ config PCIE_VISCONTI_HOST
Say Y here if you want PCIe controller support on Toshiba Visconti SoC.
This driver supports TMPV7708 SoC.
+config PCIE_ULTRARISC
+ tristate "UltraRISC PCIe host controller"
+ depends on ARCH_ULTRARISC || COMPILE_TEST
+ select PCIE_DW_HOST
+ select PCI_MSI
+ default y if ARCH_ULTRARISC
+ help
+ Enables support for the PCIe controller in the UltraRISC SoC.
+ This driver supports UR-DP1000 SoC.
+ By default, this symbol is enabled when ARCH_ULTRARISC is active,
+ requiring no further configuration on that platform.
+
endmenu
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 67ba59c02038..884c46b78e01 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PCIE_RCAR_GEN4) += pcie-rcar-gen4.o
obj-$(CONFIG_PCIE_SPACEMIT_K1) += pcie-spacemit-k1.o
obj-$(CONFIG_PCIE_STM32_HOST) += pcie-stm32.o
obj-$(CONFIG_PCIE_STM32_EP) += pcie-stm32-ep.o
+obj-$(CONFIG_PCIE_ULTRARISC) += pcie-ultrarisc.o
# The following drivers are for devices that use the generic ACPI
# pci_root.c driver but don't support standard ECAM config access.
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index ae6389dd9caa..88dcb0e7943a 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -69,6 +69,8 @@
/* Synopsys-specific PCIe configuration registers */
#define PCIE_PORT_FORCE 0x708
+/* Bit[7:0] LINK_NUM: Link Number. Not used for endpoint */
+#define PORT_LINK_NUM_MASK GENMASK(7, 0)
#define PORT_FORCE_DO_DESKEW_FOR_SRIS BIT(23)
#define PCIE_PORT_AFR 0x70C
@@ -96,6 +98,26 @@
#define PCIE_PORT_LANE_SKEW 0x714
#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0)
+/*
+ * PCIE_TIMER_CTRL_MAX_FUNC_NUM: Timer Control and Max Function Number
+ * Register.
+ * This register holds the ack frequency, latency, replay, fast link
+ * scaling timers, and max function number values.
+ * Bit[30:29] FAST_LINK_SCALING_FACTOR: Fast Link Timer Scaling Factor.
+ * 0x0 (SF_1024):Scaling Factor is 1024 (1ms is 1us).
+ * When the LTSSM is in Config or L12 Entry State, 1ms
+ * timer is 2us, 2ms timer is 4us and 3ms timer is 6us.
+ * 0x1 (SF_256): Scaling Factor is 256 (1ms is 4us)
+ * 0x2 (SF_64): Scaling Factor is 64 (1ms is 16us)
+ * 0x3 (SF_16): Scaling Factor is 16 (1ms is 64us)
+ */
+#define PCIE_TIMER_CTRL_MAX_FUNC_NUM 0x718
+#define PORT_FLT_SF_MASK GENMASK(30, 29)
+#define PORT_FLT_SF_VAL_1024 0x0
+#define PORT_FLT_SF_VAL_256 0x1
+#define PORT_FLT_SF_VAL_64 0x2
+#define PORT_FLT_SF_VAL_16 0x3
+
#define PCIE_PORT_DEBUG0 0x728
#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f
#define PORT_LOGIC_LTSSM_STATE_L0 0x11
diff --git a/drivers/pci/controller/dwc/pcie-ultrarisc.c b/drivers/pci/controller/dwc/pcie-ultrarisc.c
new file mode 100644
index 000000000000..7094ee8c532f
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-ultrarisc.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DWC PCIe RC driver for UltraRISC DP1000 SoC
+ *
+ * Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_CUS_CORE 0x400000
+
+#define LTSSM_ENABLE BIT(7)
+#define FAST_LINK_MODE BIT(12)
+#define HOLD_PHY_RST BIT(14)
+#define L1SUB_DISABLE BIT(15)
+
+struct ultrarisc_pcie {
+ struct dw_pcie *pci;
+};
+
+static struct pci_ops ultrarisc_pci_ops = {
+ .map_bus = dw_pcie_own_conf_map_bus,
+ .read = pci_generic_config_read32,
+ .write = pci_generic_config_write32,
+};
+
+static int ultrarisc_pcie_host_init(struct dw_pcie_rp *pp)
+{
+ struct pci_host_bridge *bridge = pp->bridge;
+
+ bridge->ops = &ultrarisc_pci_ops;
+
+ return 0;
+}
+
+static void ultrarisc_pcie_pme_turn_off(struct dw_pcie_rp *pp)
+{
+ /*
+ * DP1000 does not support sending PME_Turn_Off from the RC.
+ * Keep this callback empty to skip the generic MSG TLP path.
+ */
+}
+
+static const struct dw_pcie_host_ops ultrarisc_pcie_host_ops = {
+ .init = ultrarisc_pcie_host_init,
+ .pme_turn_off = ultrarisc_pcie_pme_turn_off,
+};
+
+static int ultrarisc_pcie_start_link(struct dw_pcie *pci)
+{
+ u32 val;
+ u8 cap_exp;
+
+ val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE);
+ val &= ~FAST_LINK_MODE;
+ dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val);
+
+ val = dw_pcie_readl_dbi(pci, PCIE_TIMER_CTRL_MAX_FUNC_NUM);
+ FIELD_MODIFY(PORT_FLT_SF_MASK, &val, PORT_FLT_SF_VAL_64);
+ dw_pcie_writel_dbi(pci, PCIE_TIMER_CTRL_MAX_FUNC_NUM, val);
+
+ cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ val = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCTL2);
+ FIELD_MODIFY(PCI_EXP_LNKCTL2_TLS, &val, PCI_EXP_LNKCTL2_TLS_16_0GT);
+ dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCTL2, val);
+
+ val = dw_pcie_readl_dbi(pci, PCIE_PORT_FORCE);
+ FIELD_MODIFY(PORT_LINK_NUM_MASK, &val, 0);
+ dw_pcie_writel_dbi(pci, PCIE_PORT_FORCE, val);
+
+ val = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_DEVCTL2);
+ FIELD_MODIFY(PCI_EXP_DEVCTL2_COMP_TIMEOUT, &val, 0x6);
+ dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_DEVCTL2, val);
+
+ val = dw_pcie_readl_dbi(pci, PCIE_CUS_CORE);
+ val &= ~(HOLD_PHY_RST | L1SUB_DISABLE);
+ val |= LTSSM_ENABLE;
+ dw_pcie_writel_dbi(pci, PCIE_CUS_CORE, val);
+
+ return 0;
+}
+
+static const struct dw_pcie_ops dw_pcie_ops = {
+ .start_link = ultrarisc_pcie_start_link,
+};
+
+static int ultrarisc_pcie_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ultrarisc_pcie *pcie;
+ struct dw_pcie *pci;
+ struct dw_pcie_rp *pp;
+ int ret;
+
+ pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+
+ pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
+ if (!pci)
+ return -ENOMEM;
+
+ pci->dev = dev;
+ pci->ops = &dw_pcie_ops;
+
+ /* Set a default value suitable for at most 16 in and 16 out windows */
+ pci->atu_size = SZ_8K;
+ pci->max_link_speed = 4;
+ pcie->pci = pci;
+
+ pp = &pci->pp;
+
+ platform_set_drvdata(pdev, pcie);
+
+ pp->irq = platform_get_irq(pdev, 1);
+ if (pp->irq < 0)
+ return pp->irq;
+
+ pp->num_vectors = MAX_MSI_IRQS;
+ /* No L2/L3 Ready indication is available on this platform. */
+ pp->skip_l23_ready = true;
+ pp->ops = &ultrarisc_pcie_host_ops;
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(dev, "Failed to initialize host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ultrarisc_pcie_suspend_noirq(struct device *dev)
+{
+ struct ultrarisc_pcie *pcie = dev_get_drvdata(dev);
+ struct dw_pcie *pci = pcie->pci;
+
+ return dw_pcie_suspend_noirq(pci);
+}
+
+static int ultrarisc_pcie_resume_noirq(struct device *dev)
+{
+ struct ultrarisc_pcie *pcie = dev_get_drvdata(dev);
+ struct dw_pcie *pci = pcie->pci;
+
+ return dw_pcie_resume_noirq(pci);
+}
+
+static const struct dev_pm_ops ultrarisc_pcie_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(ultrarisc_pcie_suspend_noirq,
+ ultrarisc_pcie_resume_noirq)
+};
+
+static const struct of_device_id ultrarisc_pcie_of_match[] = {
+ {
+ .compatible = "ultrarisc,dp1000-pcie",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ultrarisc_pcie_of_match);
+
+static struct platform_driver ultrarisc_pcie_driver = {
+ .driver = {
+ .name = "ultrarisc-pcie",
+ .of_match_table = ultrarisc_pcie_of_match,
+ .suppress_bind_attrs = true,
+ .pm = &ultrarisc_pcie_pm_ops,
+ },
+ .probe = ultrarisc_pcie_probe,
+};
+module_platform_driver(ultrarisc_pcie_driver);
+
+MODULE_DESCRIPTION("UltraRISC DP1000 DWC PCIe host controller");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v3 0/3] riscv: Add PCIe support for UltraRISC DP1000 SoC
From: Jia Wang @ 2026-04-15 7:21 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Jingoo Han,
Xincheng Zhang, Krzysztof Kozlowski, Conor Dooley
Cc: linux-riscv, linux-kernel, linux-pci, devicetree, Jia Wang
This patch series adds PCIe controller support for the UltraRISC DP1000 SoC.
The DP1000 is an 8-core 64-bit RISC-V SoC based on UltraRISC CP100 cores,
supporting RV64GCBHX ISA with Hardware Virtualization and RISC-V H(v1.0)
Extension.
The PCIe controller is based on Synopsys DesignWare PCIe IP.
This series adds:
- Patch 1 adds the basic SoC family Kconfig support for UltraRISC platforms.
- Patch 2 adds the device tree bindings documentation for the PCIe controller.
- Patch 3 introduces the PCIe host controller driver.
The patches have been tested on UltraRISC DP1000 development board with
various PCIe devices including NVMe SSDs and network cards, verifying
link establishment, enumeration, and basic data transfer.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
Changes in v3:
- Fold the MAINTAINERS update into the binding/driver patches and drop
the standalone MAINTAINERS patch from v2.
- Patch 1:
* Trim DP1000-specific ISA/feature details from the help text.
- Patch 2:
* Simplify the description formatting and remove the redundant.
* Drop the max-link-speed property from the binding.
* Remove the redundant interrupts description line.
* Clean up the example.
- Patch 3:
* Drop unused regmap include.
* Drop the unused irq_mask[] field.
* Set pci->max_link_speed = 4 based on the fixed hardware capability.
- Link to v2: https://patch.msgid.link/20260407-ultrarisc-pcie-v2-0-2aa2a19a7fb3@ultrarisc.com
Changes in v2:
- Rebased onto v7.0-rc7.
- Patch 1:
* Removed unnecessary 'depends' line.
* Fixed help text indentation.
- Patch 2:
* No changes.
- Patch 3:
* Updated $ref to use 'snps,dw-pcie.yaml' as the base schema.
* Add interrupts/interrupt-names (MSI + INTx).
* Drop properties covered by generic DWC/PCI host bindings;
update example accordingly.
* Verified the schema passes 'make dt_binding_check' and 'yamllint'.
- Patch 4:
* Update commit message.
* Kconfig: switch PCIE_ULTRARISC to tristate; simplify help text.
* Convert suspend/resume to dev_pm_ops and called
`dw_pcie_suspend_noirq()` / `dw_pcie_resume_noirq()`.
* Use FIELD_MODIFY(); adjust DWC header macros/comments.
* Added empty `.pme_turn_off()` callback for DP1000 limitation.
* Renamed link callback to `start_link`.
* Switched to `module_platform_driver()`.
* Formatting cleanups (headers order, spacing, variable naming,
function names)
- Link to v1: https://patch.msgid.link/20260316-ultrarisc-pcie-v1-0-ef2946ede698@ultrarisc.com
---
Jia Wang (2):
riscv: add UltraRISC SoC family Kconfig support
dt-bindings: PCI: Add UltraRISC DP1000 PCIe controller
Xincheng Zhang (1):
PCI: ultrarisc: Add UltraRISC DP1000 PCIe Root Complex driver
.../bindings/pci/ultrarisc,dp1000-pcie.yaml | 93 +++++++++++
MAINTAINERS | 8 +
arch/riscv/Kconfig.socs | 6 +
drivers/pci/controller/dwc/Kconfig | 12 ++
drivers/pci/controller/dwc/Makefile | 1 +
drivers/pci/controller/dwc/pcie-designware.h | 22 +++
drivers/pci/controller/dwc/pcie-ultrarisc.c | 186 +++++++++++++++++++++
7 files changed, 328 insertions(+)
---
base-commit: bfe62a454542cfad3379f6ef5680b125f41e20f4
change-id: 20260310-ultrarisc-pcie-494998763399
Best regards,
--
Jia Wang <wangjia@ultrarisc.com>
^ permalink raw reply
* [PATCH v3 2/3] dt-bindings: PCI: Add UltraRISC DP1000 PCIe controller
From: Jia Wang @ 2026-04-15 7:21 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Jingoo Han,
Xincheng Zhang, Krzysztof Kozlowski, Conor Dooley
Cc: linux-riscv, linux-kernel, linux-pci, devicetree, Jia Wang
In-Reply-To: <20260415-ultrarisc-pcie-v3-0-73f06e972616@ultrarisc.com>
Add UltraRISC DP1000 SoC PCIe controller devicetree bindings.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
.../bindings/pci/ultrarisc,dp1000-pcie.yaml | 93 ++++++++++++++++++++++
MAINTAINERS | 7 ++
2 files changed, 100 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/ultrarisc,dp1000-pcie.yaml b/Documentation/devicetree/bindings/pci/ultrarisc,dp1000-pcie.yaml
new file mode 100644
index 000000000000..512b935bf5d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/ultrarisc,dp1000-pcie.yaml
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/ultrarisc,dp1000-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: UltraRISC DP1000 PCIe Host Controller
+
+description:
+ UltraRISC DP1000 SoC PCIe host controller is based on the DesignWare PCIe IP.
+
+maintainers:
+ - Xincheng Zhang <zhangxincheng@ultrarisc.com>
+ - Jia Wang <wangjia@ultrarisc.com>
+
+allOf:
+ - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
+properties:
+ compatible:
+ const: ultrarisc,dp1000-pcie
+
+ reg:
+ items:
+ - description: Data Bus Interface (DBI) registers.
+ - description: PCIe configuration space region.
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: config
+
+ num-lanes:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [4, 16]
+ description: Number of lanes to use.
+
+ interrupts:
+ items:
+ - description: MSI interrupt
+ - description: Legacy INTA interrupt
+ - description: Legacy INTB interrupt
+ - description: Legacy INTC interrupt
+ - description: Legacy INTD interrupt
+
+ interrupt-names:
+ items:
+ - const: msi
+ - const: inta
+ - const: intb
+ - const: intc
+ - const: intd
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie@21000000 {
+ compatible = "ultrarisc,dp1000-pcie";
+ reg = <0x0 0x21000000 0x0 0x01000000>,
+ <0x0 0x4fff0000 0x0 0x00010000>;
+ reg-names = "dbi", "config";
+ ranges = <0x81000000 0x0 0x4fbf0000 0x0 0x4fbf0000 0x0 0x00400000>,
+ <0x82000000 0x0 0x40000000 0x0 0x40000000 0x0 0x0fbf0000>,
+ <0xc3000000 0x40 0x00000000 0x40 0x00000000 0xd 0x00000000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ dma-coherent;
+ bus-range = <0x0 0xff>;
+ num-lanes = <16>;
+ interrupt-parent = <&plic>;
+ interrupts = <43>, <44>, <45>, <46>, <47>;
+ interrupt-names = "msi", "inta", "intb", "intc", "intd";
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &plic 44>,
+ <0x0 0x0 0x0 0x2 &plic 45>,
+ <0x0 0x0 0x0 0x3 &plic 46>,
+ <0x0 0x0 0x0 0x4 &plic 47>;
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index c3fe46d7c4bc..2ec02d8443dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20582,6 +20582,13 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
F: drivers/pci/controller/plda/pcie-starfive.c
+PCIE DRIVER FOR ULTRARISC DP1000
+M: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+M: Jia Wang <wangjia@ultrarisc.com>
+L: linux-pci@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pci/ultrarisc,dp1000-pcie.yaml
+
PCIE ENDPOINT DRIVER FOR QUALCOMM
M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-pci@vger.kernel.org
--
2.34.1
^ permalink raw reply related
* [PATCH v3 1/3] riscv: add UltraRISC SoC family Kconfig support
From: Jia Wang @ 2026-04-15 7:21 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Jingoo Han,
Xincheng Zhang, Krzysztof Kozlowski, Conor Dooley
Cc: linux-riscv, linux-kernel, linux-pci, devicetree, Jia Wang
In-Reply-To: <20260415-ultrarisc-pcie-v3-0-73f06e972616@ultrarisc.com>
The first SoC in the UltraRISC series is UR-DP1000, containing octa
UltraRISC CP100 cores.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
arch/riscv/Kconfig.socs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index d621b85dd63b..0b4d06a7b4bf 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -84,6 +84,12 @@ config ARCH_THEAD
help
This enables support for the RISC-V based T-HEAD SoCs.
+config ARCH_ULTRARISC
+ bool "UltraRISC RISC-V SoCs"
+ help
+ This enables support for UltraRISC SoC platform hardware,
+ including boards based on the UR-DP1000.
+
config ARCH_VIRT
bool "QEMU Virt Machine"
select POWER_RESET
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v4 07/13] mfd: sec: set DMA coherent mask
From: Krzysztof Kozlowski @ 2026-04-15 7:19 UTC (permalink / raw)
To: Kaustabh Chakraborty
Cc: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
André Draszik, Alexandre Belloni, Jonathan Corbet,
Shuah Khan, Nam Tran, Łukasz Lebiedziński, linux-leds,
devicetree, linux-kernel, linux-pm, linux-samsung-soc, linux-rtc,
linux-doc
In-Reply-To: <20260414-s2mu005-pmic-v4-7-7fe7480577e6@disroot.org>
On Tue, Apr 14, 2026 at 12:02:59PM +0530, Kaustabh Chakraborty wrote:
> Kernel logs are filled with "DMA mask not set" messages for every
> sub-device. The device does not use DMA for communication, so these
> messages are useless. Disable the coherent DMA mask for the PMIC device,
> which is also propagated to sub-devices.
>
> Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
> ---
> Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml | 3 +++
> drivers/mfd/sec-common.c | 3 +++
> 2 files changed, 6 insertions(+)
>
Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v4 04/13] dt-bindings: power: supply: document Samsung S2M series PMIC charger device
From: Krzysztof Kozlowski @ 2026-04-15 7:18 UTC (permalink / raw)
To: Kaustabh Chakraborty
Cc: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
André Draszik, Alexandre Belloni, Jonathan Corbet,
Shuah Khan, Nam Tran, Łukasz Lebiedziński, linux-leds,
devicetree, linux-kernel, linux-pm, linux-samsung-soc, linux-rtc,
linux-doc
In-Reply-To: <20260414-s2mu005-pmic-v4-4-7fe7480577e6@disroot.org>
On Tue, Apr 14, 2026 at 12:02:56PM +0530, Kaustabh Chakraborty wrote:
> +description: |
> + The Samsung S2M series PMIC battery charger manages power interfacing
> + of the USB port. It may supply power, as done in USB OTG operation
> + mode, or it may accept power and redirect it to the battery fuelgauge
> + for charging.
> +
> + This is a part of device tree bindings for S2M and S5M family of Power
> + Management IC (PMIC).
> +
> + See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
> + additional information and example.
> +
> +allOf:
> + - $ref: power-supply.yaml#
> +
> +properties:
> + compatible:
> + enum:
> + - samsung,s2mu005-charger
> +
> + port:
> + $ref: /schemas/graph.yaml#/properties/port
That port is internal part of the device, thus should be dropped which
leaves you with only one property - monitored battery - and therefore
fold the node into the parent node.
Best regards,
Krzysztof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox