From 8ce761dd8720430afe230eb2544d367999cce964 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 27 Aug 2026 10:34:28 +0800 Subject: [PATCH] PENDING: media: qcom: camss: csid: Program CSID wrapper path domain ID on Nord On Nord the full CSID (CSID 900) sits behind a wrapper region that holds a per-RDI path domain_id. The domain_id selects which SMMU SID the RDI write path uses; a domain_id of 0 selects an unmapped SID, so RDI writes never reach memory and captured frames are silently dropped. Add the optional per-CSID "csid_wrapper" reg regions to the binding and the camss node, plumb the optional wrapper_base through the CSID driver, and program a non-zero domain_id for every enabled virtual channel from the CSID 900 configure_stream path so RDI writes target the IFE SID that the device tree maps via "iommus". Signed-off-by: Wenmeng Liu --- .../bindings/media/qcom,nord-camss.yaml | 11 +++++++- arch/arm64/boot/dts/qcom/nord-embedded.dtsi | 6 +++++ .../platform/qcom/camss/camss-csid-900.c | 26 +++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.c | 9 +++++++ .../media/platform/qcom/camss/camss-csid.h | 1 + drivers/media/platform/qcom/camss/camss.c | 6 ++--- 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml b/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml index 93dbb55e1a974..ff4b24bf4ee36 100644 --- a/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml @@ -17,13 +17,16 @@ properties: const: qcom,nord-camss reg: - maxItems: 29 + maxItems: 32 reg-names: items: - const: csid0 - const: csid1 - const: csid2 + - const: csid_wrapper0 + - const: csid_wrapper1 + - const: csid_wrapper2 - const: csid_lite0 - const: csid_lite1 - const: csid_lite2 @@ -199,6 +202,9 @@ examples: reg = <0 0x09b32000 0 0x2000>, <0 0x09b38800 0 0x2000>, <0 0x09b3f000 0 0x2000>, + <0 0x09b31000 0 0x1000>, + <0 0x09b37800 0 0x1000>, + <0 0x09b3e000 0 0x1000>, <0 0x09c32000 0 0x1000>, <0 0x09c37000 0 0x1000>, <0 0x09c3c000 0 0x1000>, @@ -229,6 +235,9 @@ examples: reg-names = "csid0", "csid1", "csid2", + "csid_wrapper0", + "csid_wrapper1", + "csid_wrapper2", "csid_lite0", "csid_lite1", "csid_lite2", diff --git a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi index 80e3dafb03c99..d94e7c1f05cbb 100644 --- a/arch/arm64/boot/dts/qcom/nord-embedded.dtsi +++ b/arch/arm64/boot/dts/qcom/nord-embedded.dtsi @@ -1067,6 +1067,9 @@ reg = <0 0x09b32000 0 0x2000>, <0 0x09b38800 0 0x2000>, <0 0x09b3f000 0 0x2000>, + <0 0x09b31000 0 0x1000>, + <0 0x09b37800 0 0x1000>, + <0 0x09b3e000 0 0x1000>, <0 0x09c32000 0 0x1000>, <0 0x09c37000 0 0x1000>, <0 0x09c3c000 0 0x1000>, @@ -1097,6 +1100,9 @@ reg-names = "csid0", "csid1", "csid2", + "csid_wrapper0", + "csid_wrapper1", + "csid_wrapper2", "csid_lite0", "csid_lite1", "csid_lite2", diff --git a/drivers/media/platform/qcom/camss/camss-csid-900.c b/drivers/media/platform/qcom/camss/camss-csid-900.c index 18aaa6e1bf9cf..b11fbe1957985 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-900.c +++ b/drivers/media/platform/qcom/camss/camss-csid-900.c @@ -93,6 +93,14 @@ #define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x11C + 0x10 * (rdi)) #define INFO_RUP_DONE BIT(23) +/* + * Per-path domain_id (CSID wrapper, full CSID only). A domain_id of 0 selects + * an unmapped SMMU SID, so RDI writes never reach memory; program a non-zero + * value to select the IFE SID that the device tree maps via "iommus". + */ +#define CSID_PATH_DOMAIN_ID_CFG1 0x4 +#define PATH_DOMAIN_ID_RDI(rdi) (1U << ((rdi) * 8)) + static void __csid_aup_rup_trigger(struct csid_device *csid) { writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); @@ -233,12 +241,30 @@ static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 writel(val, csid->base + rdi_cfg0_offset); } +static void __csid_configure_domain_id(struct csid_device *csid) +{ + u32 val; + int i; + + if (csid_is_lite(csid) || !csid->wrapper_base) + return; + + val = readl(csid->wrapper_base + CSID_PATH_DOMAIN_ID_CFG1); + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) + if (csid->phy.en_vc & BIT(i)) + val |= PATH_DOMAIN_ID_RDI(i); + writel(val, csid->wrapper_base + CSID_PATH_DOMAIN_ID_CFG1); +} + static void csid_configure_stream(struct csid_device *csid, u8 enable) { u8 i, k; __csid_configure_rx(csid, &csid->phy); + if (enable) + __csid_configure_domain_id(csid); + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { if (csid->phy.en_vc & BIT(i)) { __csid_configure_rdi_stream(csid, enable, i, 0); diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index 48459b46a981b..1e8f7ea6e1875 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -1130,6 +1130,15 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, return PTR_ERR(csid->base); } + /* Optional per-CSID wrapper region (e.g. secure control on CSID 900) */ + + if (res->reg[1]) { + csid->wrapper_base = + devm_platform_ioremap_resource_byname(pdev, res->reg[1]); + if (IS_ERR(csid->wrapper_base)) + return PTR_ERR(csid->wrapper_base); + } + /* Interrupt */ ret = platform_get_irq_byname(pdev, res->interrupt[0]); diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 6b04ff77bf459..dcac369f0ac70 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -154,6 +154,7 @@ struct csid_device { struct v4l2_subdev subdev; struct media_pad pads[MSM_CSID_PADS_NUM]; void __iomem *base; + void __iomem *wrapper_base; u32 irq; char irq_name[30]; union { diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 3025e742047bf..7e8e1ee01b1ac 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -427,7 +427,7 @@ static const struct camss_subdev_resources csid_res_nord[] = { .clock_rate = { { 400000000, 480000000 }, { 400000000, 480000000 }, { 0 } }, - .reg = { "csid0" }, + .reg = { "csid0", "csid_wrapper0" }, .interrupt = { "csid0" }, .csid = { .is_lite = false, @@ -442,7 +442,7 @@ static const struct camss_subdev_resources csid_res_nord[] = { .clock_rate = { { 400000000, 480000000 }, { 400000000, 480000000 }, { 0 } }, - .reg = { "csid1" }, + .reg = { "csid1", "csid_wrapper1" }, .interrupt = { "csid1" }, .csid = { .is_lite = false, @@ -457,7 +457,7 @@ static const struct camss_subdev_resources csid_res_nord[] = { .clock_rate = { { 400000000, 480000000 }, { 400000000, 480000000 }, { 0 } }, - .reg = { "csid2" }, + .reg = { "csid2", "csid_wrapper2" }, .interrupt = { "csid2" }, .csid = { .is_lite = false,