* [PATCH v3 3/6] arm64: dts: qcom: shikra: Add CCI definitions
From: Nihal Kumar Gupta @ 2026-06-15 7:12 UTC (permalink / raw)
To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Robert Foss, Andi Shyti, Bryan O'Donoghue,
Bjorn Andersson, Konrad Dybcio, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel, linux-i2c,
imx, linux-arm-kernel, Suresh Vankadara, Vikram Sharma,
Nihal Kumar Gupta
In-Reply-To: <20260615-shikra-camss-review-v3-0-8183481f48d0@oss.qualcomm.com>
Qualcomm Shikra SoC has one Camera Control Interface (CCI)
containing two I2C hosts.
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra.dtsi | 70 ++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi
index f0e827996609dab2c09834857a1bffd9560155a6..57732804a6c6a114a407a4a541a1cc7af7635ea2 100644
--- a/arch/arm64/boot/dts/qcom/shikra.dtsi
+++ b/arch/arm64/boot/dts/qcom/shikra.dtsi
@@ -348,6 +348,38 @@ tlmm: pinctrl@500000 {
gpio-ranges = <&tlmm 0 0 165>;
wakeup-parent = <&mpm>;
+ cci_i2c0_default: cci-i2c0-default-state {
+ /* SDA, SCL */
+ pins = "gpio36", "gpio37";
+ function = "cci_i2c0";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci_i2c0_sleep: cci-i2c0-sleep-state {
+ /* SDA, SCL */
+ pins = "gpio36", "gpio37";
+ function = "cci_i2c0";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ cci_i2c1_default: cci-i2c1-default-state {
+ /* SDA, SCL */
+ pins = "gpio41", "gpio42";
+ function = "cci_i2c1";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci_i2c1_sleep: cci-i2c1-sleep-state {
+ /* SDA, SCL */
+ pins = "gpio41", "gpio42";
+ function = "cci_i2c1";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
qup_uart0_default: qup-uart0-default-state {
pins = "gpio0", "gpio1";
function = "qup0_se0";
@@ -702,6 +734,44 @@ port@1 {
reg = <1>;
};
};
+
+ };
+
+ cci: cci@5c1b000 {
+ compatible = "qcom,shikra-cci", "qcom,msm8996-cci";
+ reg = <0x0 0x05c1b000 0x0 0x1000>;
+
+ interrupts = <GIC_SPI 206 IRQ_TYPE_EDGE_RISING 0>;
+
+ clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>,
+ <&gcc GCC_CAMSS_CCI_0_CLK>;
+ clock-names = "ahb",
+ "cci";
+
+ power-domains = <&gcc GCC_CAMSS_TOP_GDSC>;
+
+ pinctrl-0 = <&cci_i2c0_default &cci_i2c1_default>;
+ pinctrl-1 = <&cci_i2c0_sleep &cci_i2c1_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ cci_i2c0: i2c-bus@0 {
+ reg = <0>;
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ cci_i2c1: i2c-bus@1 {
+ reg = <1>;
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
qupv3_0: geniqup@4ac0000 {
--
2.34.1
^ permalink raw reply related
* [PATCH v3 2/6] arm64: dts: qcom: shikra: Add CAMSS node
From: Nihal Kumar Gupta @ 2026-06-15 7:12 UTC (permalink / raw)
To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Robert Foss, Andi Shyti, Bryan O'Donoghue,
Bjorn Andersson, Konrad Dybcio, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel, linux-i2c,
imx, linux-arm-kernel, Suresh Vankadara, Vikram Sharma,
Nihal Kumar Gupta
In-Reply-To: <20260615-shikra-camss-review-v3-0-8183481f48d0@oss.qualcomm.com>
Add the Camera Subsystem node. Shikra shares the same IP as QCM2290
with two CSIPHYs, two CSIDs and two VFEs, but does not include CDM
and OPE blocks, so only a single IOMMU context bank is needed.
Co-developed-by: Vikram Sharma <vikram.sharma@oss.qualcomm.com>
Signed-off-by: Vikram Sharma <vikram.sharma@oss.qualcomm.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/shikra.dtsi | 100 +++++++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/shikra.dtsi b/arch/arm64/boot/dts/qcom/shikra.dtsi
index a4334d99c1f35ee851ca8266ec37d4a200a07ee5..f0e827996609dab2c09834857a1bffd9560155a6 100644
--- a/arch/arm64/boot/dts/qcom/shikra.dtsi
+++ b/arch/arm64/boot/dts/qcom/shikra.dtsi
@@ -604,6 +604,106 @@ opp-384000000 {
};
};
+ camss: camss@5c11000 {
+ compatible = "qcom,shikra-camss", "qcom,qcm2290-camss";
+
+ reg = <0x0 0x05c11000 0x0 0x1000>,
+ <0x0 0x05c6e000 0x0 0x1000>,
+ <0x0 0x05c75000 0x0 0x1000>,
+ <0x0 0x05c52000 0x0 0x1000>,
+ <0x0 0x05c53000 0x0 0x1000>,
+ <0x0 0x05c66000 0x0 0x400>,
+ <0x0 0x05c68000 0x0 0x400>,
+ <0x0 0x05c6f000 0x0 0x4000>,
+ <0x0 0x05c76000 0x0 0x4000>;
+ reg-names = "top",
+ "csid0",
+ "csid1",
+ "csiphy0",
+ "csiphy1",
+ "csitpg0",
+ "csitpg1",
+ "vfe0",
+ "vfe1";
+
+ clocks = <&gcc GCC_CAMERA_AHB_CLK>,
+ <&gcc GCC_CAMSS_AXI_CLK>,
+ <&gcc GCC_CAMSS_NRT_AXI_CLK>,
+ <&gcc GCC_CAMSS_RT_AXI_CLK>,
+ <&gcc GCC_CAMSS_TFE_0_CSID_CLK>,
+ <&gcc GCC_CAMSS_TFE_1_CSID_CLK>,
+ <&gcc GCC_CAMSS_CPHY_0_CLK>,
+ <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>,
+ <&gcc GCC_CAMSS_CPHY_1_CLK>,
+ <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>,
+ <&gcc GCC_CAMSS_TOP_AHB_CLK>,
+ <&gcc GCC_CAMSS_TFE_0_CLK>,
+ <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>,
+ <&gcc GCC_CAMSS_TFE_1_CLK>,
+ <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>;
+ clock-names = "ahb",
+ "axi",
+ "camnoc_nrt_axi",
+ "camnoc_rt_axi",
+ "csi0",
+ "csi1",
+ "csiphy0",
+ "csiphy0_timer",
+ "csiphy1",
+ "csiphy1_timer",
+ "top_ahb",
+ "vfe0",
+ "vfe0_cphy_rx",
+ "vfe1",
+ "vfe1_cphy_rx";
+
+ interrupts = <GIC_SPI 210 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 212 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 72 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 73 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 309 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 310 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 211 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 213 IRQ_TYPE_EDGE_RISING 0>;
+ interrupt-names = "csid0",
+ "csid1",
+ "csiphy0",
+ "csiphy1",
+ "csitpg0",
+ "csitpg1",
+ "vfe0",
+ "vfe1";
+
+ interconnects = <&mem_noc MASTER_AMPSS_M0 RPM_ACTIVE_TAG
+ &config_noc SLAVE_CAMERA_CFG RPM_ACTIVE_TAG>,
+ <&mmrt_virt MASTER_CAMNOC_HF RPM_ALWAYS_TAG
+ &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
+ <&mmnrt_virt MASTER_CAMNOC_SF RPM_ALWAYS_TAG
+ &mc_virt SLAVE_EBI_CH0 RPM_ALWAYS_TAG>;
+ interconnect-names = "ahb",
+ "hf_mnoc",
+ "sf_mnoc";
+
+ iommus = <&apps_smmu 0x400 0x0>;
+
+ power-domains = <&gcc GCC_CAMSS_TOP_GDSC>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
qupv3_0: geniqup@4ac0000 {
compatible = "qcom,geni-se-qup";
reg = <0x0 0x04ac0000 0x0 0x2000>;
--
2.34.1
^ permalink raw reply related
* [PATCH v3 1/6] dt-bindings: media: qcom: Add Shikra CAMSS compatible
From: Nihal Kumar Gupta @ 2026-06-15 7:12 UTC (permalink / raw)
To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Robert Foss, Andi Shyti, Bryan O'Donoghue,
Bjorn Andersson, Konrad Dybcio, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel, linux-i2c,
imx, linux-arm-kernel, Suresh Vankadara, Vikram Sharma,
Nihal Kumar Gupta, Krzysztof Kozlowski
In-Reply-To: <20260615-shikra-camss-review-v3-0-8183481f48d0@oss.qualcomm.com>
Shikra contains the same Camera Subsystem IP as QCM2290. Document the
platform-specific compatible string, using qcom,qcm2290-camss as
fallback.
Unlike QCM2290, Shikra omits the CDM and OPE blocks, requiring only a
single IOMMU context bank instead of four.
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
.../devicetree/bindings/media/qcom,qcm2290-camss.yaml | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml
index 391d0f6f67ef5fdfea31dd3683477561516b1556..490a7f3a8c5ff9c624f46150ee651793811823de 100644
--- a/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml
+++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-camss.yaml
@@ -14,7 +14,11 @@ description:
properties:
compatible:
- const: qcom,qcm2290-camss
+ oneOf:
+ - items:
+ - const: qcom,shikra-camss
+ - const: qcom,qcm2290-camss
+ - const: qcom,qcm2290-camss
reg:
maxItems: 9
@@ -76,7 +80,14 @@ properties:
- const: sf_mnoc
iommus:
- maxItems: 4
+ oneOf:
+ - items:
+ - description: S1 HLOS VFE non-protected (VFE only)
+ - items:
+ - description: S1 HLOS VFE non-protected
+ - description: S1 HLOS CDM non-protected
+ - description: S1 HLOS OPE read non-protected
+ - description: S1 HLOS OPE write non-protected
power-domains:
items:
--
2.34.1
^ permalink raw reply related
* [PATCH v3 0/6] Add CAMSS and IMX577 sensor support for Shikra EVK
From: Nihal Kumar Gupta @ 2026-06-15 7:12 UTC (permalink / raw)
To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Robert Foss, Andi Shyti, Bryan O'Donoghue,
Bjorn Andersson, Konrad Dybcio, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-arm-msm, linux-media, devicetree, linux-kernel, linux-i2c,
imx, linux-arm-kernel, Suresh Vankadara, Vikram Sharma,
Nihal Kumar Gupta, Krzysztof Kozlowski
Shikra EVK is based on the Qualcomm Shikra SoC.
It lacks a camera sensor in its default configuration.
This series adds CAMSS driver support, CCI definitions and enables
the 22-pin IMX577 sensor via CSIPHY1 through device tree overlays.
We have tested IMX577 Sensor on CCI1 with following commands:
- media-ctl --reset
- media-ctl -d /dev/media0 -V '"imx577 1-001a":0[fmt:SRGGB10/4056x3040 field:none]'
- media-ctl -d /dev/media0 -V '"msm_csiphy1":0[fmt:SRGGB10/4056x3040]'
- media-ctl -d /dev/media0 -V '"msm_csid0":0[fmt:SRGGB10/4056x3040]'
- media-ctl -d /dev/media0 -V '"msm_vfe0_rdi0":0[fmt:SRGGB10/4056x3040]'
- media-ctl -d /dev/media0 -l '"msm_csiphy1":1->"msm_csid0":0[1]'
- media-ctl -d /dev/media0 -l '"msm_csid0":1->"msm_vfe0_rdi0":0[1]'
- yavta -B capture-mplane -c -I -n 5 -f SRGGB10P -s 4056x3040 -F /dev/video0
Used following tools for the sanity check of these changes.
- make -j32 W=1
- checkpatch.pl
- make DT_CHECKER_FLAGS=-m W=1 DT_SCHEMA_FILES=i2c/qcom,i2c-cci.yaml dt_binding_check
- make DT_CHECKER_FLAGS=-m DT_SCHEMA_FILES=media/qcom,qcm2290-camss.yaml dt_binding_check W=1
- make CHECK_DTBS=y W=1 qcom/qrb2210-rb1-vision-mezzanine.dtb
- make CHECK_DTBS=1 W=1 qcom/shikra-cqm-cqs-evk-imx577-camera.dtb
- make CHECK_DTBS=1 W=1 qcom/shikra-iqs-evk-imx577-camera.dtb
- make CHECK_DTBS=y W=1 dtbs
The Shikra CAMSS binding patch does not depend on the rest of the series
and can go through the media tree on its own.
This patch series depends on patch series:
https://lore.kernel.org/all/20260527-shikra-dt-v4-0-b5ca1fa0b392@oss.qualcomm.com/
https://lore.kernel.org/all/20260608-shikra-gcc-rpmcc-clks-v5-0-94cefe092ee3@oss.qualcomm.com/
Signed-off-by: Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
---
Changes in v3:
- Drop dt-bindings: i2c: qcom-cci: Document Shikra compatible; already
picked by Andi Shyti into her i2c tree (now in linux-next as e3a8f8329397)
- Preserve blank line after compatible const in qcom,qcm2290-camss.yaml (Krzysztof)
- Add blank line between iommus and power-domains in CAMSS node (Vladimir)
- Fix data-lanes numbering to start from 1 in all endpoints (Vladimir)
- Move cam1_reset_default pinctrl state from board .dts files into the
mezzanine .dtso overlay files (Vladimir)
- Collect Reviewed-by tags
- Link to v2: https://lore.kernel.org/r/20260608-shikra-camss-review-v2-0-ca1936bf1219@oss.qualcomm.com
Changes in v2:
- Drop qcm2390_resources struct and CAMSS_2390 enum; use qcom,qcm2290-camss
as fallback compatible string since Shikra CAMSS is register-compatible
with QCM2290 (Loic, Bryan)
- Use oneOf in iommus to describe all valid SID combinations: VFE-only
(Shikra) and VFE+CDM+OPE read+OPE write (QCM2290/Agatti); add
per-entry descriptions naming each SID (Krzysztof, Bryan)
- Rename shikra-cqm-evk-imx577-camera overlay to
shikra-cqm-cqs-evk-imx577-camera, shared by both CQM and CQS EVK
boards which use the same PM4125 PMIC and camera supply rails (Bryan)
- Add reset-gpios pinctrl state for IMX577 sensor (gpio33, cam1-reset-default-state)
- Add comment in overlay DTS explaining absent regulators are powered
by the daughter board (Bryan)
- Collect Reviewed-by tags
- Add reset-gpios pinctrl state for IMX577 sensor.
- Link to v1: https://lore.kernel.org/r/20260526-shikra-camss-review-v1-0-645d2c8c75a7@qti.qualcomm.com
---
Nihal Kumar Gupta (6):
dt-bindings: media: qcom: Add Shikra CAMSS compatible
arm64: dts: qcom: shikra: Add CAMSS node
arm64: dts: qcom: shikra: Add CCI definitions
arm64: dts: qcom: shikra: Add pin configuration for mclks
arm64: dts: qcom: shikra-cqm-cqs-evk-imx577-camera: Add DT overlay
arm64: dts: qcom: shikra-iqs-evk-imx577-camera: Add DT overlay
.../bindings/media/qcom,qcm2290-camss.yaml | 15 +-
arch/arm64/boot/dts/qcom/Makefile | 8 +
.../dts/qcom/shikra-cqm-cqs-evk-imx577-camera.dtso | 79 ++++++++
.../dts/qcom/shikra-iqs-evk-imx577-camera.dtso | 79 ++++++++
arch/arm64/boot/dts/qcom/shikra.dtsi | 198 +++++++++++++++++++++
5 files changed, 377 insertions(+), 2 deletions(-)
---
base-commit: abe651837cb394f76d738a7a747322fca3bf17ba
change-id: 20260526-shikra-camss-review-cf6f66ac566b
prerequisite-change-id: 20260511-shikra-dt-d75d97454646:v4
prerequisite-patch-id: 3a689e8dda5fd2755b689d94d095806b3f2e6eed
prerequisite-patch-id: 2acc300a68ed8c5364fb5f2f7d28fc0d56ab07bf
prerequisite-patch-id: 2357cac636e019eaf14d6a493a1c72bca56fe405
prerequisite-patch-id: 2885f299e711582da312ca9d13983d296a3dd5dc
prerequisite-patch-id: 91af5f3c01e766a53ce8de69aa21847a2d6bbbf8
prerequisite-change-id: 20260429-shikra-gcc-rpmcc-clks-2094edfff3b0:v5
prerequisite-patch-id: 59bb0a7828e41f546f734f127d81da83c0adcda9
prerequisite-patch-id: 197da6bcb15cadc47869dba88c8020987b25c335
prerequisite-patch-id: 8ec9c1eb03f052ae232ed54117abed38672c23f6
prerequisite-patch-id: 350db4f4bcdfc0fad9ed57cd5b1723f85ad44f5d
Best regards,
--
Nihal Kumar Gupta <nihal.gupta@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table
From: sashiko-bot @ 2026-06-15 7:02 UTC (permalink / raw)
To: Joey Lu; +Cc: conor+dt, dri-devel, devicetree, robh
In-Reply-To: <20260615065003.76661-4-a0987203069@gmail.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
New issues:
- [High] The newly introduced `crtc_disable` hardware hook is invoked after disabling the pixel clock, which will cause unclocked hardware accesses and potential bus hangs.
- [High] The disable sequence for the display panel incorrectly swaps the order of clearing PANEL_START and PANEL_CONFIG, violating the required reverse-enable hardware sequence.
Pre-existing issues:
- [High] Sleepable clock control functions (`clk_prepare_enable` and `clk_disable_unprepare`) are called inside DRM atomic commit callbacks where sleeping is strictly forbidden.
- [High] The primary plane disable logic incorrectly sets the `VSDC_FB_CONFIG_EX_FB_EN` bit instead of clearing it, failing to actually disable the plane.
- [High] Calling `regmap_read` in a hardirq handler uses a standard spinlock which maps to a sleeping `rt_mutex` on PREEMPT_RT.
- [High] Primary plane update programs hardware registers with unclipped destination coordinates (`state->crtc_x` / `state->crtc_y`) which can be negative.
--
commit 7db852133467fb896e651ada4802a06233540439
Author: Joey Lu <a0987203069@gmail.com>
drm/verisilicon: introduce per-variant hardware ops table
This commit introduces a hardware operations table for different variants
of the Verisilicon display controller. It extracts DC8200-specific ops
into a new file and updates the bridge, CRTC, and plane code to use the
new vtable instead of direct register access.
> diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c
> index 0b8a35d09cd2e..679d6541ba1b9 100644
> --- a/drivers/gpu/drm/verisilicon/vs_crtc.c
> +++ b/drivers/gpu/drm/verisilicon/vs_crtc.c
[ ... ]
> @@ -26,10 +49,16 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
> struct vs_dc *dc = vcrtc->dc;
> unsigned int output = vcrtc->id;
>
> drm_crtc_vblank_off(crtc);
>
> clk_disable_unprepare(dc->pix_clk[output]);
[Severity: High]
This is a pre-existing issue, but does calling clk_disable_unprepare() here
and clk_prepare_enable() in vs_crtc_atomic_enable() cause a sleep in atomic
context?
Since atomic_enable and atomic_disable callbacks execute in an atomic
context during non-blocking commits, calling sleepable clock control
functions could lead to deadlocks or kernel panics.
> +
> + if (dc->funcs->crtc_disable)
> + dc->funcs->crtc_disable(dc, output);
> }
[Severity: High]
Does this sequence write to hardware registers while the pixel clock is
disabled?
Calling dc->funcs->crtc_disable(dc, output) after clk_disable_unprepare()
means we are performing register accesses without a running clock, which
could lead to bus hangs or failed writes.
Should the order be reversed to match the symmetric enable sequence?
[ ... ]
> diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
> new file mode 100644
> index 0000000000000..800df9279e9b6
> --- /dev/null
> +++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
[ ... ]
> +static void vs_dc8200_panel_disable_ex(struct vs_dc *dc, unsigned int output)
> +{
> + regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
> + VSDC_DISP_PANEL_CONFIG_RUNNING);
> + regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
> + VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
> + VSDC_DISP_PANEL_START_RUNNING(output));
> +
> + regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
> + VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
> +}
[Severity: High]
Does this swap the order of clearing the panel registers compared to the
original vs_bridge_atomic_disable() code?
The original code correctly cleared VSDC_DISP_PANEL_START before
VSDC_DISP_PANEL_CONFIG.
Clearing CONFIG while the display pipeline is still actively running could
cause an unprotected hardware state transition, leading to pipeline
underflows or hardware hangs.
[ ... ]
> +static void vs_dc8200_primary_plane_disable_ex(struct vs_dc *dc, unsigned int output)
> +{
> + regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
> + VSDC_FB_CONFIG_EX_FB_EN);
> +
> + vs_dc8200_plane_commit(dc, output);
> +}
[Severity: High]
This is a pre-existing issue, but does this function actually disable the
plane?
It looks like regmap_set_bits() is used on VSDC_FB_CONFIG_EX_FB_EN, which
would keep the plane enabled in hardware.
Should this use regmap_clear_bits() instead to properly clear the bit and
disable the plane?
> +static void vs_dc8200_primary_plane_update_ex(struct vs_dc *dc, unsigned int output,
> + struct drm_plane_state *state)
> +{
> + regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
> + VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
> + regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
> + VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
> + state->crtc_y + state->crtc_h));
[Severity: High]
This is a pre-existing issue, but what happens if the user provides negative
coordinates when a plane is partially off-screen?
Because state->crtc_x and state->crtc_y are unclipped, a negative value
passed to VSDC_MAKE_PLANE_POS() might be bitwise ANDed with 0x7fff,
producing a massive positive value (for example, -10 becomes 32758).
Should clipped coordinates be used here instead to avoid incorrect display
output?
[ ... ]
> +static u32 vs_dc8200_irq_ack(struct vs_dc *dc)
> +{
> + u32 irqs;
> +
> + regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
> + return irqs;
> +}
[Severity: High]
This is a pre-existing issue, but could this regmap_read() cause a
sleep-in-atomic panic on PREEMPT_RT systems?
Since this is invoked from vs_dc_irq_handler() in hardirq context, and the
regmap configuration does not seem to set use_raw_spinlock = true, the
regmap infrastructure uses a standard spinlock.
On PREEMPT_RT, this maps to a sleepable rt_mutex.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615065003.76661-1-a0987203069@gmail.com?part=3
^ permalink raw reply
* Re: [PATCH 2/2] clk: ultrarisc: add DP1000 clock driver
From: Jia Wang @ 2026-06-15 7:01 UTC (permalink / raw)
To: sashiko-reviews; +Cc: Jia Wang via B4 Relay, devicetree, robh, conor+dt
In-Reply-To: <20260611095617.765C81F00898@smtp.kernel.org>
On 2026-06-11 09:56 +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> - [High] Missing clocks in `clk_data->hws` evaluate to `NULL` instead of an error pointer, creating dummy clocks.
> - [High] Read-modify-write operations on clock control registers fail to mask the self-clearing load bit, risking spurious loads and preventing divider updates.
> - [Low] Missing `<linux/module.h>` include.
> --
>
> commit 8cba5aa205eda7abb58c5b279348bd81f69fdc45
> Author: Jia Wang <wangjia@ultrarisc.com>
>
> clk: ultrarisc: add DP1000 clock driver
>
> Add a clock driver for the UltraRISC DP1000 SoC.
>
> The clock tree is driven by a SYSPLL and provides fixed-factor clocks for
> the subsystem and PCIe, divider-based root clocks for GMAC and the UART,
> I2C, and SPI blocks, and per-instance gate clocks for UART0-3, I2C0-3,
> and SPI0-1.
>
> > diff --git a/drivers/clk/ultrarisc/clk-ultrarisc.c b/drivers/clk/ultrarisc/clk-ultrarisc.c
> > index 0000000000000..2b970565a4be8
> > --- /dev/null
> > +++ b/drivers/clk/ultrarisc/clk-ultrarisc.c
> > @@ -0,0 +1,417 @@
> [ ... ]
> > +#include <linux/bitfield.h>
> > +#include <linux/clk-provider.h>
>
> [Severity: Low]
> Should <linux/module.h> be explicitly included here?
>
> The file uses module macros like MODULE_DESCRIPTION and EXPORT_SYMBOL_GPL(),
> and relying on implicit inclusion can sometimes cause build failures.
>
Thanks. I'll add linux/module.h explicitly.
> [ ... ]
> > +static int ultrarisc_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> > + unsigned long parent_rate)
> > +{
> [ ... ]
> > + scoped_guard(spinlock_irqsave, divider->lock) {
> > + val = readl_relaxed(divider->reg);
> > + val &= ~(clk_div_mask(divider->width) << divider->shift);
> > + val |= value << divider->shift;
> > + writel_relaxed(val, divider->reg);
>
> [Severity: High]
> Does this read-modify-write sequence need to mask out divider_clk->load_mask
> from the read value before the first write?
>
> If the hardware hasn't cleared the bit from a previous operation, the first
> write could write it as 1. Then the second write (below) would also write 1,
> failing to provide the required 0->1 transition to trigger the hardware.
>
The load bit is write-only and always reads as 0, so it is not affected by
the read-modify-write sequence. The second write is intentionally used to
trigger the hardware update after programming the divider value.
I will also add a comment to clarify this behavior in the code.
> > +
> > + if (divider_clk->load_mask) {
> > + /*
> > + * The divider update is triggered by writing 1 to the
> > + * self-clearing load bit after programming the new
> > + * divider field.
> > + */
> > + writel_relaxed(val | divider_clk->load_mask,
> > + divider->reg);
> > + }
> > + }
> > +
> > + return 0;
> > +}
>
> [ ... ]
> > +static struct clk_hw *
> > +ultrarisc_clk_register_divider(struct device *dev,
> > + const struct ultrarisc_divider_desc *desc,
> > + struct clk_hw *parent_hw, void __iomem *base,
> > + spinlock_t *lock)
> > +{
> [ ... ]
> > + if (desc->gate_bit != ULTRARISC_CLK_NO_GATE) {
> > + divider->gate.reg = reg;
> > + divider->gate.bit_idx = desc->gate_bit;
> > + divider->gate.flags = desc->gate_flags;
> > + divider->gate.lock = lock;
> > + gate_hw = ÷r->gate.hw;
> > + gate_ops = &clk_gate_ops;
>
> [Severity: High]
> Can using the standard clk_gate_ops here cause spurious loads?
>
> The standard gate ops perform a generic read-modify-write. If a gate
> operation executes while the load_mask bit is still 1, it will blindly
> write 1 back to the load bit, potentially triggering a spurious hardware
> reload or corrupting the update state machine.
>
On DP1000 the load bit always reads back as 0, so a generic gate
read-modify-write cycle cannot preserve a stale asserted load bit and
write it back as 1.
Because of that, clk_gate_ops does not cause a spurious reload on this
hardware.
> > + }
> > +
> > + return devm_clk_hw_register_composite_pdata(dev, desc->name, &pdata, 1,
> > + NULL, NULL,
> > + ÷r->divider.hw,
> > + &ultrarisc_divider_ops,
> > + gate_hw, gate_ops,
> > + CLK_GET_RATE_NOCACHE);
> > +}
>
> [ ... ]
> > +static int ultrarisc_clk_register_fixed_factors(struct device *dev,
> > + struct clk_hw_onecell_data *clk_data,
> > + const struct ultrarisc_clk_soc_data *soc_data)
> > +{
> [ ... ]
> > + parent_hw = clk_data->hws[desc->parent_id];
> > + if (!parent_hw)
> > + return -EINVAL;
>
> [Severity: High]
> If the clk_data initialization (below) is fixed to use error pointers
> instead of NULL, should this validation check use IS_ERR_OR_NULL() or
> IS_ERR() to avoid dereferencing an ERR_PTR?
>
> > +
> > + hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, desc->name,
> > + parent_hw,
>
> [ ... ]
> > +int ultrarisc_clk_probe(struct platform_device *pdev,
> > + const struct ultrarisc_clk_soc_data *soc_data)
> > +{
> [ ... ]
> > + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws,
> > + soc_data->num_clks),
> > + GFP_KERNEL);
>
> [Severity: High]
> Since this array is zero-initialized, any unpopulated clock IDs will remain
> NULL. Does this need to be explicitly filled with ERR_PTR(-ENOENT)?
>
> When a consumer requests an invalid clock index, of_clk_hw_onecell_get()
> returns this NULL pointer. The clock framework considers NULL a valid
> optional dummy clock, allowing consumer drivers to silently succeed at
> enabling the clock instead of failing. If they then access peripheral
> registers without the clock actually being enabled, it could trigger a bus
> fault.
>
For the current UltraRISC clock data, all clock IDs in the advertised
[0, num_clks) range are populated before the provider is registered, so
no in-range NULL entry is exposed to consumers.
Within the driver, clk_data->hws[] is zero-initialized and missing
entries are represented as NULL rather than ERR_PTR values, so the
local parent checks only need to handle NULL. I'll add an explicit
hws[] completeness check before provider registration in the next
version.
> > + if (!clk_data)
> > + return -ENOMEM;
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260611-ultrarisc-clock-v1-0-2d93ebb4cc13@ultrarisc.com?part=2
>
Best regards,
Jia Wang
^ permalink raw reply
* Re: [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB
From: sashiko-bot @ 2026-06-15 6:59 UTC (permalink / raw)
To: Joey Lu; +Cc: conor+dt, dri-devel, robh, devicetree
In-Reply-To: <20260615065003.76661-6-a0987203069@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] A wildcard entry in vs_chip_identities shadows specific customer ID entries, making them unreachable.
- [High] The function vs_fill_chip_identity() ignores the return values of regmap_read() calls, leading to potential use of uninitialized stack memory.
--
commit a6a5d6f3773180ae44a10c5525c46667d81239fe
Author: Joey Lu <a0987203069@gmail.com>
drm/verisilicon: add DCUltraLite chip identity to HWDB
Register the Nuvoton MA35D1 DCUltraLite chip identity in
vs_chip_identities[]:
model = 0x0 (DCUltraLite; Verisilicon uses 0 for this IP)
[ ... ]
> diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
> index 91524d16f7785..7d630a667a3f0 100644
> --- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
> +++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
[ ... ]
> @@ -129,6 +129,16 @@ static struct vs_chip_identity vs_chip_identities[] = {
> .max_cursor_size = 64,
> .formats = &vs_formats_no_yuv444,
> },
> + {
> + .model = 0x0, /* DCUltraLite */
> + .revision = 0x5560,
> + .customer_id = 0x305,
> +
> + .generation = VSDC_GEN_DC8000,
> + .display_count = 1,
> + .max_cursor_size = 32,
> + .formats = &vs_formats_no_yuv444,
> + },
> };
>
> int vs_fill_chip_identity(struct regmap *regs,
> struct vs_chip_identity *ident)
> {
> u32 model;
> u32 revision;
> u32 customer_id;
> int i;
>
> regmap_read(regs, VSDC_TOP_CHIP_MODEL, &model);
> regmap_read(regs, VSDC_TOP_CHIP_REV, &revision);
> regmap_read(regs, VSDC_TOP_CHIP_CUSTOMER_ID, &customer_id);
[Severity: High]
This isn't a bug introduced by this patch, but does vs_fill_chip_identity()
ignore the return values of these regmap_read() calls?
The regmap_read() API returns an integer error code on failure and leaves
the output pointer's target unmodified.
If any of these reads fail due to bus errors or unmapped I/O, will the
function proceed to use uninitialized stack memory in the loop to compare
against the vs_chip_identities array?
>
> for (i = 0; i < ARRAY_SIZE(vs_chip_identities); i++) {
> if (vs_chip_identities[i].model == model &&
> vs_chip_identities[i].revision == revision &&
> (vs_chip_identities[i].customer_id == customer_id ||
> vs_chip_identities[i].customer_id == ~0U)) {
> memcpy(ident, &vs_chip_identities[i], sizeof(*ident));
> ident->customer_id = customer_id;
> return 0;
> }
[Severity: High]
This is a pre-existing issue, but does the wildcard entry in
vs_chip_identities[] shadow specific customer ID entries?
Looking at vs_chip_identities[] in drivers/gpu/drm/verisilicon/vs_hwdb.c,
there is a wildcard entry at the beginning of the array:
{
.model = 0x8200,
.revision = 0x5720,
.customer_id = ~0U,
...
}
Since vs_fill_chip_identity() searches sequentially and returns on the first
match, will any hardware with model 0x8200 and revision 0x5720 instantly
match this wildcard entry?
If so, the specific configurations for customer IDs 0x310 and 0x311 defined
later in the array might be completely shadowed and never reached. This would
cause customer ID 0x310 to incorrectly use vs_formats_no_yuv444 instead of
its intended vs_formats_with_yuv444.
> }
>
> return -EINVAL;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615065003.76661-1-a0987203069@gmail.com?part=5
^ permalink raw reply
* Re: [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants
From: sashiko-bot @ 2026-06-15 6:55 UTC (permalink / raw)
To: Joey Lu; +Cc: devicetree, robh, dri-devel, conor+dt
In-Reply-To: <20260615065003.76661-2-a0987203069@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The top-level `clock-names` property enforces a strict positional sequence (`core`, `axi`, `ahb`, `pix0`, `pix1`) that conflicts with the `nuvoton,ma35d1-dcu` variant, causing valid device trees to fail schema validation.
--
commit 644d6513333f2ad52d35609ed1c0190fdeaa8192
Author: Joey Lu <a0987203069@gmail.com>
dt-bindings: display: verisilicon,dc: generalize for single-output variants
This commit generalizes the verisilicon,dc schema to support single-output
variants. It extracts variant-specific constraints into allOf/if blocks and
adds support for the Nuvoton MA35D1 SoC.
> diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> --- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
> +++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
[ ... ]
> clock-names:
> + minItems: 2
> + maxItems: 5
> items:
> - const: core
> - const: axi
> - const: ahb
> - const: pix0
> - const: pix1
[ ... ]
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: nuvoton,ma35d1-dcu
> + then:
> + properties:
> + clocks:
> + minItems: 2
> + maxItems: 2
> + items:
> + - description: DC Core clock
> + - description: Pixel clock of output 0
> +
> + clock-names:
> + minItems: 2
> + maxItems: 2
[Severity: Medium]
Will this cause validation failures for valid device trees?
The top-level clock-names defines a strict positional sequence where the
second item must be "axi". However, the clocks definition for the
nuvoton,ma35d1-dcu variant indicates it uses "core" and "pix0".
Since the variant's clock-names block doesn't redefine the items array, won't
dt-schema evaluate "pix0" against the inherited "axi" constraint at index 1
and fail?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615065003.76661-1-a0987203069@gmail.com?part=1
^ permalink raw reply
* [PATCH v2 2/2] pinctrl: qcom: Add the tlmm driver for Maili platform
From: Jingyi Wang @ 2026-06-15 6:55 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: aiqun.yu, tingwei.zhang, trilok.soni, yijie.yang, linux-arm-msm,
linux-gpio, devicetree, linux-kernel, Jingyi Wang
In-Reply-To: <20260614-maili-pinctrl-v2-0-0db5bfc23d64@oss.qualcomm.com>
Add support for Maili TLMM configuration and control via the pinctrl
framework.
Signed-off-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
---
drivers/pinctrl/qcom/Kconfig.msm | 10 +
drivers/pinctrl/qcom/Makefile | 1 +
drivers/pinctrl/qcom/pinctrl-maili.c | 1630 ++++++++++++++++++++++++++++++++++
3 files changed, 1641 insertions(+)
diff --git a/drivers/pinctrl/qcom/Kconfig.msm b/drivers/pinctrl/qcom/Kconfig.msm
index 9409e678ec6d..42875457b5fc 100644
--- a/drivers/pinctrl/qcom/Kconfig.msm
+++ b/drivers/pinctrl/qcom/Kconfig.msm
@@ -153,6 +153,16 @@ config PINCTRL_KAANAPALI
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc Kaanapali platform.
+config PINCTRL_MAILI
+ tristate "Qualcomm Technologies Inc Maili pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ default ARCH_QCOM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Maili platform.
+ Say Y here to compile statically, or M here to compile it as a module.
+ If unsure, say N.
+
config PINCTRL_MSM8226
tristate "Qualcomm 8226 pin controller driver"
depends on ARM || COMPILE_TEST
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 93cc4e7965ca..43ecd246afe8 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_IPQ6018) += pinctrl-ipq6018.o
obj-$(CONFIG_PINCTRL_IPQ9574) += pinctrl-ipq9574.o
obj-$(CONFIG_PINCTRL_IPQ9650) += pinctrl-ipq9650.o
obj-$(CONFIG_PINCTRL_KAANAPALI) += pinctrl-kaanapali.o
+obj-$(CONFIG_PINCTRL_MAILI) += pinctrl-maili.o
obj-$(CONFIG_PINCTRL_MSM8226) += pinctrl-msm8226.o
obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
diff --git a/drivers/pinctrl/qcom/pinctrl-maili.c b/drivers/pinctrl/qcom/pinctrl-maili.c
new file mode 100644
index 000000000000..984b7444a2c1
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-maili.c
@@ -0,0 +1,1630 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-msm.h"
+
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+ { \
+ .grp = PINCTRL_PINGROUP("gpio" #id, \
+ gpio##id##_pins, \
+ ARRAY_SIZE(gpio##id##_pins)), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9, \
+ msm_mux_##f10, \
+ msm_mux_##f11 /* egpio mode */ \
+ }, \
+ .nfuncs = 12, \
+ .ctl_reg = REG_SIZE * id, \
+ .io_reg = 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = 0x8 + REG_SIZE * id, \
+ .intr_status_reg = 0xc + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .egpio_enable = 12, \
+ .egpio_present = 11, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_wakeup_present_bit = 6, \
+ .intr_wakeup_enable_bit = 7, \
+ .intr_target_bit = 8, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+#define UFS_RESET(pg_name, ctl, io) \
+ { \
+ .grp = PINCTRL_PINGROUP(#pg_name, \
+ pg_name##_pins, \
+ ARRAY_SIZE(pg_name##_pins)), \
+ .ctl_reg = ctl, \
+ .io_reg = io, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+static const struct pinctrl_pin_desc maili_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "GPIO_150"),
+ PINCTRL_PIN(151, "GPIO_151"),
+ PINCTRL_PIN(152, "GPIO_152"),
+ PINCTRL_PIN(153, "GPIO_153"),
+ PINCTRL_PIN(154, "GPIO_154"),
+ PINCTRL_PIN(155, "GPIO_155"),
+ PINCTRL_PIN(156, "GPIO_156"),
+ PINCTRL_PIN(157, "GPIO_157"),
+ PINCTRL_PIN(158, "GPIO_158"),
+ PINCTRL_PIN(159, "GPIO_159"),
+ PINCTRL_PIN(160, "GPIO_160"),
+ PINCTRL_PIN(161, "GPIO_161"),
+ PINCTRL_PIN(162, "GPIO_162"),
+ PINCTRL_PIN(163, "GPIO_163"),
+ PINCTRL_PIN(164, "GPIO_164"),
+ PINCTRL_PIN(165, "GPIO_165"),
+ PINCTRL_PIN(166, "GPIO_166"),
+ PINCTRL_PIN(167, "GPIO_167"),
+ PINCTRL_PIN(168, "GPIO_168"),
+ PINCTRL_PIN(169, "GPIO_169"),
+ PINCTRL_PIN(170, "GPIO_170"),
+ PINCTRL_PIN(171, "GPIO_171"),
+ PINCTRL_PIN(172, "GPIO_172"),
+ PINCTRL_PIN(173, "GPIO_173"),
+ PINCTRL_PIN(174, "GPIO_174"),
+ PINCTRL_PIN(175, "GPIO_175"),
+ PINCTRL_PIN(176, "GPIO_176"),
+ PINCTRL_PIN(177, "GPIO_177"),
+ PINCTRL_PIN(178, "GPIO_178"),
+ PINCTRL_PIN(179, "GPIO_179"),
+ PINCTRL_PIN(180, "GPIO_180"),
+ PINCTRL_PIN(181, "GPIO_181"),
+ PINCTRL_PIN(182, "GPIO_182"),
+ PINCTRL_PIN(183, "GPIO_183"),
+ PINCTRL_PIN(184, "GPIO_184"),
+ PINCTRL_PIN(185, "GPIO_185"),
+ PINCTRL_PIN(186, "GPIO_186"),
+ PINCTRL_PIN(187, "GPIO_187"),
+ PINCTRL_PIN(188, "GPIO_188"),
+ PINCTRL_PIN(189, "GPIO_189"),
+ PINCTRL_PIN(190, "GPIO_190"),
+ PINCTRL_PIN(191, "GPIO_191"),
+ PINCTRL_PIN(192, "GPIO_192"),
+ PINCTRL_PIN(193, "GPIO_193"),
+ PINCTRL_PIN(194, "GPIO_194"),
+ PINCTRL_PIN(195, "GPIO_195"),
+ PINCTRL_PIN(196, "GPIO_196"),
+ PINCTRL_PIN(197, "GPIO_197"),
+ PINCTRL_PIN(198, "GPIO_198"),
+ PINCTRL_PIN(199, "GPIO_199"),
+ PINCTRL_PIN(200, "GPIO_200"),
+ PINCTRL_PIN(201, "GPIO_201"),
+ PINCTRL_PIN(202, "GPIO_202"),
+ PINCTRL_PIN(203, "GPIO_203"),
+ PINCTRL_PIN(204, "GPIO_204"),
+ PINCTRL_PIN(205, "GPIO_205"),
+ PINCTRL_PIN(206, "GPIO_206"),
+ PINCTRL_PIN(207, "GPIO_207"),
+ PINCTRL_PIN(208, "GPIO_208"),
+ PINCTRL_PIN(209, "GPIO_209"),
+ PINCTRL_PIN(210, "GPIO_210"),
+ PINCTRL_PIN(211, "GPIO_211"),
+ PINCTRL_PIN(212, "GPIO_212"),
+ PINCTRL_PIN(213, "GPIO_213"),
+ PINCTRL_PIN(214, "GPIO_214"),
+ PINCTRL_PIN(215, "GPIO_215"),
+ PINCTRL_PIN(216, "GPIO_216"),
+ PINCTRL_PIN(217, "GPIO_217"),
+ PINCTRL_PIN(218, "GPIO_218"),
+ PINCTRL_PIN(219, "GPIO_219"),
+ PINCTRL_PIN(220, "GPIO_220"),
+ PINCTRL_PIN(221, "GPIO_221"),
+ PINCTRL_PIN(222, "GPIO_222"),
+ PINCTRL_PIN(223, "GPIO_223"),
+ PINCTRL_PIN(224, "GPIO_224"),
+ PINCTRL_PIN(225, "GPIO_225"),
+ PINCTRL_PIN(226, "UFS_RESET"),
+ PINCTRL_PIN(227, "SDC2_CLK"),
+ PINCTRL_PIN(228, "SDC2_CMD"),
+ PINCTRL_PIN(229, "SDC2_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+DECLARE_MSM_GPIO_PINS(152);
+DECLARE_MSM_GPIO_PINS(153);
+DECLARE_MSM_GPIO_PINS(154);
+DECLARE_MSM_GPIO_PINS(155);
+DECLARE_MSM_GPIO_PINS(156);
+DECLARE_MSM_GPIO_PINS(157);
+DECLARE_MSM_GPIO_PINS(158);
+DECLARE_MSM_GPIO_PINS(159);
+DECLARE_MSM_GPIO_PINS(160);
+DECLARE_MSM_GPIO_PINS(161);
+DECLARE_MSM_GPIO_PINS(162);
+DECLARE_MSM_GPIO_PINS(163);
+DECLARE_MSM_GPIO_PINS(164);
+DECLARE_MSM_GPIO_PINS(165);
+DECLARE_MSM_GPIO_PINS(166);
+DECLARE_MSM_GPIO_PINS(167);
+DECLARE_MSM_GPIO_PINS(168);
+DECLARE_MSM_GPIO_PINS(169);
+DECLARE_MSM_GPIO_PINS(170);
+DECLARE_MSM_GPIO_PINS(171);
+DECLARE_MSM_GPIO_PINS(172);
+DECLARE_MSM_GPIO_PINS(173);
+DECLARE_MSM_GPIO_PINS(174);
+DECLARE_MSM_GPIO_PINS(175);
+DECLARE_MSM_GPIO_PINS(176);
+DECLARE_MSM_GPIO_PINS(177);
+DECLARE_MSM_GPIO_PINS(178);
+DECLARE_MSM_GPIO_PINS(179);
+DECLARE_MSM_GPIO_PINS(180);
+DECLARE_MSM_GPIO_PINS(181);
+DECLARE_MSM_GPIO_PINS(182);
+DECLARE_MSM_GPIO_PINS(183);
+DECLARE_MSM_GPIO_PINS(184);
+DECLARE_MSM_GPIO_PINS(185);
+DECLARE_MSM_GPIO_PINS(186);
+DECLARE_MSM_GPIO_PINS(187);
+DECLARE_MSM_GPIO_PINS(188);
+DECLARE_MSM_GPIO_PINS(189);
+DECLARE_MSM_GPIO_PINS(190);
+DECLARE_MSM_GPIO_PINS(191);
+DECLARE_MSM_GPIO_PINS(192);
+DECLARE_MSM_GPIO_PINS(193);
+DECLARE_MSM_GPIO_PINS(194);
+DECLARE_MSM_GPIO_PINS(195);
+DECLARE_MSM_GPIO_PINS(196);
+DECLARE_MSM_GPIO_PINS(197);
+DECLARE_MSM_GPIO_PINS(198);
+DECLARE_MSM_GPIO_PINS(199);
+DECLARE_MSM_GPIO_PINS(200);
+DECLARE_MSM_GPIO_PINS(201);
+DECLARE_MSM_GPIO_PINS(202);
+DECLARE_MSM_GPIO_PINS(203);
+DECLARE_MSM_GPIO_PINS(204);
+DECLARE_MSM_GPIO_PINS(205);
+DECLARE_MSM_GPIO_PINS(206);
+DECLARE_MSM_GPIO_PINS(207);
+DECLARE_MSM_GPIO_PINS(208);
+DECLARE_MSM_GPIO_PINS(209);
+DECLARE_MSM_GPIO_PINS(210);
+DECLARE_MSM_GPIO_PINS(211);
+DECLARE_MSM_GPIO_PINS(212);
+DECLARE_MSM_GPIO_PINS(213);
+DECLARE_MSM_GPIO_PINS(214);
+DECLARE_MSM_GPIO_PINS(215);
+DECLARE_MSM_GPIO_PINS(216);
+DECLARE_MSM_GPIO_PINS(217);
+DECLARE_MSM_GPIO_PINS(218);
+DECLARE_MSM_GPIO_PINS(219);
+DECLARE_MSM_GPIO_PINS(220);
+DECLARE_MSM_GPIO_PINS(221);
+DECLARE_MSM_GPIO_PINS(222);
+DECLARE_MSM_GPIO_PINS(223);
+DECLARE_MSM_GPIO_PINS(224);
+DECLARE_MSM_GPIO_PINS(225);
+
+static const unsigned int ufs_reset_pins[] = { 226 };
+static const unsigned int sdc2_clk_pins[] = { 227 };
+static const unsigned int sdc2_cmd_pins[] = { 228 };
+static const unsigned int sdc2_data_pins[] = { 229 };
+
+enum maili_functions {
+ msm_mux_gpio,
+ msm_mux_aoss_cti,
+ msm_mux_atest_char,
+ msm_mux_atest_usb,
+ msm_mux_audio_ext_mclk,
+ msm_mux_audio_ref_clk,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async_in,
+ msm_mux_cci_i2c0,
+ msm_mux_cci_i2c1,
+ msm_mux_cci_i2c2,
+ msm_mux_cci_i2c3,
+ msm_mux_cci_timer,
+ msm_mux_coex_espmi,
+ msm_mux_coex_uart1_rx,
+ msm_mux_coex_uart1_tx,
+ msm_mux_dbg_out_clk,
+ msm_mux_ddr_bist,
+ msm_mux_ddr_pxi,
+ msm_mux_dp_hot,
+ msm_mux_egpio,
+ msm_mux_gcc_gp,
+ msm_mux_gnss_adc,
+ msm_mux_host2wlan_sol,
+ msm_mux_host_rst,
+ msm_mux_i2chub0_se0,
+ msm_mux_i2chub0_se1,
+ msm_mux_i2chub0_se2,
+ msm_mux_i2chub0_se3,
+ msm_mux_i2chub0_se4,
+ msm_mux_i2s0,
+ msm_mux_i2s1,
+ msm_mux_ibi_i3c,
+ msm_mux_ibi_i3c_qup5_se0,
+ msm_mux_jitter_bist,
+ msm_mux_mdp_esync0,
+ msm_mux_mdp_esync1,
+ msm_mux_mdp_esync2,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync_e,
+ msm_mux_mdp_vsync_p,
+ msm_mux_mdp_vsync0_out,
+ msm_mux_mdp_vsync1_out,
+ msm_mux_mdp_vsync2_out,
+ msm_mux_mdp_vsync3_out,
+ msm_mux_mdp_vsync5_out,
+ msm_mux_modem_pps_in,
+ msm_mux_modem_pps_out,
+ msm_mux_nav_gpio,
+ msm_mux_nav_gpio0,
+ msm_mux_nav_gpio3,
+ msm_mux_nav_rffe,
+ msm_mux_pcie0_clk_req_n,
+ msm_mux_pcie1_clk_req_n,
+ msm_mux_pcie1_rst_n,
+ msm_mux_phase_flag,
+ msm_mux_pll_bist_sync,
+ msm_mux_pll_clk_aux,
+ msm_mux_qdss_cti,
+ msm_mux_qlink,
+ msm_mux_qspi,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qup1_se0,
+ msm_mux_qup1_se1,
+ msm_mux_qup1_se2,
+ msm_mux_qup1_se3,
+ msm_mux_qup1_se4,
+ msm_mux_qup1_se5,
+ msm_mux_qup1_se6,
+ msm_mux_qup1_se7,
+ msm_mux_qup2_se0,
+ msm_mux_qup2_se1,
+ msm_mux_qup2_se2,
+ msm_mux_qup2_se3,
+ msm_mux_qup2_se4_01,
+ msm_mux_qup2_se4_23,
+ msm_mux_qup3_se0,
+ msm_mux_qup3_se1,
+ msm_mux_qup3_se2,
+ msm_mux_qup3_se3,
+ msm_mux_qup3_se4,
+ msm_mux_qup3_se5,
+ msm_mux_qup4_se0,
+ msm_mux_qup4_se1,
+ msm_mux_qup4_se2,
+ msm_mux_qup4_se3_01,
+ msm_mux_qup4_se3_23,
+ msm_mux_qup4_se3_l3,
+ msm_mux_qup4_se4_01,
+ msm_mux_qup4_se4_23,
+ msm_mux_qup4_se4_l3,
+ msm_mux_qup5_se0,
+ msm_mux_rng_rosc,
+ msm_mux_sd_write_protect,
+ msm_mux_sdc2_clk,
+ msm_mux_sdc2_cmd,
+ msm_mux_sdc2_data,
+ msm_mux_sdc2_rclk,
+ msm_mux_sdc4_clk,
+ msm_mux_sdc4_cmd,
+ msm_mux_sdc4_data,
+ msm_mux_sys_throttle,
+ msm_mux_tb_trig_sdc,
+ msm_mux_tmess_rng,
+ msm_mux_tsense_clm,
+ msm_mux_tsense_pwm,
+ msm_mux_uim0,
+ msm_mux_uim1,
+ msm_mux_usb0_hs,
+ msm_mux_usb_phy,
+ msm_mux_vfr,
+ msm_mux_vsense_trigger_mirnat,
+ msm_mux_wcn_sw,
+ msm_mux__,
+};
+
+static const char *const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", "gpio17",
+ "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41",
+ "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53",
+ "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", "gpio59",
+ "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65",
+ "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71",
+ "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88", "gpio89",
+ "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+ "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101",
+ "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107",
+ "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113",
+ "gpio114", "gpio115", "gpio116", "gpio117", "gpio118", "gpio119",
+ "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
+ "gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131",
+ "gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137",
+ "gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
+ "gpio144", "gpio145", "gpio146", "gpio147", "gpio148", "gpio149",
+ "gpio150", "gpio151", "gpio152", "gpio153", "gpio154", "gpio155",
+ "gpio156", "gpio157", "gpio158", "gpio159", "gpio160", "gpio161",
+ "gpio162", "gpio163", "gpio164", "gpio165", "gpio166", "gpio167",
+ "gpio168", "gpio169", "gpio170", "gpio171", "gpio172", "gpio173",
+ "gpio174", "gpio175", "gpio176", "gpio177", "gpio178", "gpio179",
+ "gpio180", "gpio181", "gpio182", "gpio183", "gpio184", "gpio185",
+ "gpio186", "gpio187", "gpio188", "gpio189", "gpio190", "gpio191",
+ "gpio192", "gpio193", "gpio194", "gpio195", "gpio196", "gpio197",
+ "gpio198", "gpio199", "gpio200", "gpio201", "gpio202", "gpio203",
+ "gpio204", "gpio205", "gpio206", "gpio207", "gpio208", "gpio209",
+ "gpio210", "gpio211", "gpio212", "gpio213", "gpio214", "gpio215",
+ "gpio216", "gpio217", "gpio218", "gpio219", "gpio220", "gpio221",
+ "gpio222", "gpio223", "gpio224", "gpio225",
+};
+
+static const char *const aoss_cti_groups[] = {
+ "gpio74", "gpio75", "gpio76", "gpio77",
+};
+
+static const char *const atest_char_groups[] = {
+ "gpio126", "gpio127", "gpio128", "gpio129", "gpio133",
+};
+
+static const char *const atest_usb_groups[] = {
+ "gpio78", "gpio79", "gpio102", "gpio103", "gpio104",
+};
+
+static const char *const audio_ext_mclk_groups[] = {
+ "gpio120", "gpio121",
+};
+
+static const char *const audio_ref_clk_groups[] = {
+ "gpio120",
+};
+
+static const char *const cam_mclk_groups[] = {
+ "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+};
+
+static const char *const cci_async_in_groups[] = {
+ "gpio15", "gpio109", "gpio110",
+};
+
+static const char *const cci_i2c0_groups[] = {
+ "gpio109", "gpio110",
+};
+
+static const char *const cci_i2c1_groups[] = {
+ "gpio111", "gpio112",
+};
+
+static const char *const cci_i2c2_groups[] = {
+ "gpio113", "gpio114",
+};
+
+static const char *const cci_i2c3_groups[] = {
+ "gpio107", "gpio160",
+};
+
+static const char *const cci_timer_groups[] = {
+ "gpio105", "gpio106", "gpio107", "gpio159", "gpio160",
+};
+
+static const char *const coex_espmi_groups[] = {
+ "gpio144", "gpio145",
+};
+
+static const char *const coex_uart1_rx_groups[] = {
+ "gpio144",
+};
+
+static const char *const coex_uart1_tx_groups[] = {
+ "gpio145",
+};
+
+static const char *const dbg_out_clk_groups[] = {
+ "gpio82",
+};
+
+static const char *const ddr_bist_groups[] = {
+ "gpio40", "gpio41", "gpio44", "gpio45",
+};
+
+static const char *const ddr_pxi_groups[] = {
+ "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73",
+};
+
+static const char *const dp_hot_groups[] = {
+ "gpio47",
+};
+
+static const char *const egpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
+ "gpio6", "gpio7", "gpio28", "gpio29", "gpio30", "gpio31",
+ "gpio48", "gpio49", "gpio50", "gpio51", "gpio163", "gpio164",
+ "gpio165", "gpio166", "gpio167", "gpio168", "gpio169", "gpio170",
+ "gpio171", "gpio172", "gpio173", "gpio174", "gpio175", "gpio176",
+ "gpio177", "gpio178", "gpio179", "gpio180", "gpio181", "gpio182",
+ "gpio183", "gpio184", "gpio185", "gpio186", "gpio187", "gpio188",
+ "gpio189", "gpio190", "gpio191", "gpio192", "gpio193", "gpio194",
+ "gpio195", "gpio196", "gpio197", "gpio198", "gpio199", "gpio200",
+ "gpio201", "gpio202", "gpio203", "gpio204", "gpio205", "gpio206",
+ "gpio207", "gpio208", "gpio209", "gpio212", "gpio213", "gpio214",
+ "gpio215", "gpio216", "gpio217", "gpio218",
+};
+
+static const char *const gcc_gp_groups[] = {
+ "gpio17", "gpio86", "gpio87", "gpio97", "gpio155", "gpio156",
+};
+
+static const char *const gnss_adc_groups[] = {
+ "gpio18", "gpio19", "gpio20", "gpio23",
+};
+
+static const char *const host2wlan_sol_groups[] = {
+ "gpio204",
+};
+
+static const char *const host_rst_groups[] = {
+ "gpio106",
+};
+
+static const char *const i2chub0_se0_groups[] = {
+ "gpio66", "gpio67",
+};
+
+static const char *const i2chub0_se1_groups[] = {
+ "gpio78", "gpio79",
+};
+
+static const char *const i2chub0_se2_groups[] = {
+ "gpio68", "gpio69",
+};
+
+static const char *const i2chub0_se3_groups[] = {
+ "gpio70", "gpio71",
+};
+
+static const char *const i2chub0_se4_groups[] = {
+ "gpio72", "gpio73",
+};
+
+static const char *const i2s0_groups[] = {
+ "gpio46", "gpio84", "gpio161", "gpio162",
+};
+
+static const char *const i2s1_groups[] = {
+ "gpio222", "gpio223", "gpio224", "gpio225",
+};
+
+static const char *const ibi_i3c_groups[] = {
+ "gpio0", "gpio1", "gpio4", "gpio5", "gpio8", "gpio9",
+ "gpio12", "gpio13", "gpio24", "gpio25", "gpio28", "gpio29",
+ "gpio32", "gpio33", "gpio36", "gpio37", "gpio48", "gpio49",
+ "gpio60", "gpio61", "gpio64", "gpio65", "gpio85", "gpio89",
+ "gpio117", "gpio118",
+};
+
+static const char *const ibi_i3c_qup5_se0_groups[] = {
+ "gpio8", "gpio9",
+};
+
+static const char *const jitter_bist_groups[] = {
+ "gpio73",
+};
+
+static const char *const mdp_esync0_groups[] = {
+ "gpio88", "gpio100",
+};
+
+static const char *const mdp_esync1_groups[] = {
+ "gpio86", "gpio100",
+};
+
+static const char *const mdp_esync2_groups[] = {
+ "gpio87", "gpio97",
+};
+
+static const char *const mdp_vsync_groups[] = {
+ "gpio86", "gpio87", "gpio88", "gpio97",
+};
+
+static const char *const mdp_vsync_e_groups[] = {
+ "gpio98",
+};
+
+static const char *const mdp_vsync_p_groups[] = {
+ "gpio98",
+};
+
+static const char *const mdp_vsync0_out_groups[] = {
+ "gpio86",
+};
+
+static const char *const mdp_vsync1_out_groups[] = {
+ "gpio86",
+};
+
+static const char *const mdp_vsync2_out_groups[] = {
+ "gpio87",
+};
+
+static const char *const mdp_vsync3_out_groups[] = {
+ "gpio87",
+};
+
+static const char *const mdp_vsync5_out_groups[] = {
+ "gpio87",
+};
+
+static const char *const modem_pps_in_groups[] = {
+ "gpio151",
+};
+
+static const char *const modem_pps_out_groups[] = {
+ "gpio151",
+};
+
+static const char *const nav_gpio_groups[] = {
+ "gpio146", "gpio147", "gpio148", "gpio151",
+};
+
+static const char *const nav_gpio0_groups[] = {
+ "gpio150",
+};
+
+static const char *const nav_gpio3_groups[] = {
+ "gpio150",
+};
+
+static const char *const nav_rffe_groups[] = {
+ "gpio134", "gpio135", "gpio138", "gpio139",
+};
+
+static const char *const pcie0_clk_req_n_groups[] = {
+ "gpio103",
+};
+
+static const char *const pcie1_clk_req_n_groups[] = {
+ "gpio221",
+};
+
+static const char *const pcie1_rst_n_groups[] = {
+ "gpio220",
+};
+
+static const char *const phase_flag_groups[] = {
+ "gpio40", "gpio41", "gpio44", "gpio45", "gpio46", "gpio47", "gpio126",
+ "gpio127", "gpio128", "gpio129", "gpio130", "gpio131", "gpio132",
+ "gpio133", "gpio161", "gpio162", "gpio169", "gpio170", "gpio171",
+ "gpio174", "gpio175", "gpio178", "gpio179", "gpio180", "gpio181",
+ "gpio182", "gpio183", "gpio205", "gpio222", "gpio223", "gpio224",
+ "gpio225",
+};
+
+static const char *const pll_bist_sync_groups[] = {
+ "gpio104",
+};
+
+static const char *const pll_clk_aux_groups[] = {
+ "gpio94",
+};
+
+static const char *const qdss_cti_groups[] = {
+ "gpio72", "gpio73", "gpio82", "gpio83", "gpio222", "gpio223",
+ "gpio224", "gpio225",
+};
+
+static const char *const qlink_groups[] = {
+ "gpio152", "gpio153", "gpio154",
+};
+
+static const char *const qspi_groups[] = {
+ "gpio80", "gpio81", "gpio82", "gpio147",
+};
+
+static const char *const qspi_clk_groups[] = {
+ "gpio83",
+};
+
+static const char *const qspi_cs_groups[] = {
+ "gpio146", "gpio148",
+};
+
+static const char *const qup1_se0_groups[] = {
+ "gpio222", "gpio223", "gpio224", "gpio225",
+};
+
+static const char *const qup1_se1_groups[] = {
+ "gpio74", "gpio75", "gpio76", "gpio77", "gpio188", "gpio189", "gpio192", "gpio193",
+};
+
+static const char *const qup1_se2_groups[] = {
+ "gpio40", "gpio41", "gpio42", "gpio43", "gpio130", "gpio131", "gpio132",
+};
+
+static const char *const qup1_se3_groups[] = {
+ "gpio44", "gpio45", "gpio46", "gpio47",
+};
+
+static const char *const qup1_se4_groups[] = {
+ "gpio36", "gpio37", "gpio38", "gpio39",
+};
+
+static const char *const qup1_se5_groups[] = {
+ "gpio52", "gpio53", "gpio54", "gpio55",
+};
+
+static const char *const qup1_se6_groups[] = {
+ "gpio56", "gpio57", "gpio58", "gpio59",
+};
+
+static const char *const qup1_se7_groups[] = {
+ "gpio60", "gpio61", "gpio62", "gpio63",
+};
+
+static const char *const qup2_se0_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+
+static const char *const qup2_se1_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+
+static const char *const qup2_se2_groups[] = {
+ "gpio117", "gpio118", "gpio119", "gpio120",
+};
+
+static const char *const qup2_se3_groups[] = {
+ "gpio97", "gpio122", "gpio123", "gpio124", "gpio125",
+};
+
+static const char *const qup2_se4_01_groups[] = {
+ "gpio208", "gpio209",
+};
+
+static const char *const qup2_se4_23_groups[] = {
+ "gpio208", "gpio209",
+};
+
+static const char *const qup3_se0_groups[] = {
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio82", "gpio83",
+};
+
+static const char *const qup3_se1_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio15",
+};
+
+static const char *const qup3_se2_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+
+static const char *const qup3_se3_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+
+static const char *const qup3_se4_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+
+static const char *const qup3_se5_groups[] = {
+ "gpio24", "gpio25", "gpio26", "gpio27",
+};
+
+static const char *const qup4_se0_groups[] = {
+ "gpio48", "gpio49", "gpio50", "gpio51",
+};
+
+static const char *const qup4_se1_groups[] = {
+ "gpio28", "gpio29", "gpio30", "gpio31",
+};
+
+static const char *const qup4_se2_groups[] = {
+ "gpio32", "gpio33", "gpio34", "gpio35",
+};
+
+static const char *const qup4_se3_01_groups[] = {
+ "gpio84", "gpio121",
+};
+
+static const char *const qup4_se3_23_groups[] = {
+ "gpio84", "gpio121",
+};
+
+static const char *const qup4_se3_l3_groups[] = {
+ "gpio98",
+};
+
+static const char *const qup4_se4_01_groups[] = {
+ "gpio161", "gpio162",
+};
+
+static const char *const qup4_se4_23_groups[] = {
+ "gpio161", "gpio162",
+};
+
+static const char *const qup4_se4_l3_groups[] = {
+ "gpio88",
+};
+
+static const char *const qup5_se0_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio16", "gpio17", "gpio85", "gpio89", "gpio100", "gpio214", "gpio215",
+};
+
+static const char *const rng_rosc_groups[] = {
+ "gpio64", "gpio65", "gpio66", "gpio84",
+};
+
+static const char *const sd_write_protect_groups[] = {
+ "gpio85",
+};
+
+static const char *const sdc2_clk_groups[] = {
+ "gpio56",
+};
+
+static const char *const sdc2_cmd_groups[] = {
+ "gpio57",
+};
+
+static const char *const sdc2_data_groups[] = {
+ "gpio74", "gpio75", "gpio76", "gpio77",
+};
+
+static const char *const sdc2_rclk_groups[] = {
+ "gpio54",
+};
+
+static const char *const sdc4_clk_groups[] = {
+ "gpio83",
+};
+
+static const char *const sdc4_cmd_groups[] = {
+ "gpio148",
+};
+
+static const char *const sdc4_data_groups[] = {
+ "gpio80", "gpio81", "gpio82", "gpio147",
+};
+
+static const char *const sys_throttle_groups[] = {
+ "gpio99",
+};
+
+static const char *const tb_trig_sdc_groups[] = {
+ "gpio88", "gpio146",
+};
+
+static const char *const tmess_rng_groups[] = {
+ "gpio64", "gpio65", "gpio66", "gpio84",
+};
+
+static const char *const tsense_clm_groups[] = {
+ "gpio87", "gpio97", "gpio98", "gpio99", "gpio105", "gpio106",
+ "gpio159",
+};
+
+static const char *const tsense_pwm_groups[] = {
+ "gpio35", "gpio38", "gpio58", "gpio87", "gpio97", "gpio98", "gpio99",
+};
+
+static const char *const uim0_groups[] = {
+ "gpio126", "gpio127", "gpio128", "gpio129",
+};
+
+static const char *const uim1_groups[] = {
+ "gpio36", "gpio37", "gpio39", "gpio54", "gpio55", "gpio56", "gpio70",
+ "gpio71", "gpio72", "gpio130", "gpio131", "gpio132", "gpio133",
+};
+
+static const char *const usb0_hs_groups[] = {
+ "gpio79",
+};
+
+static const char *const usb_phy_groups[] = {
+ "gpio59", "gpio60",
+};
+
+static const char *const vfr_groups[] = {
+ "gpio146", "gpio151",
+};
+
+static const char *const vsense_trigger_mirnat_groups[] = {
+ "gpio16",
+};
+
+static const char *const wcn_sw_groups[] = {
+ "gpio18", "gpio19", "gpio155", "gpio156",
+};
+
+static const struct pinfunction maili_functions[] = {
+ MSM_GPIO_PIN_FUNCTION(gpio),
+ MSM_PIN_FUNCTION(aoss_cti),
+ MSM_PIN_FUNCTION(atest_char),
+ MSM_PIN_FUNCTION(atest_usb),
+ MSM_PIN_FUNCTION(audio_ext_mclk),
+ MSM_PIN_FUNCTION(audio_ref_clk),
+ MSM_PIN_FUNCTION(cam_mclk),
+ MSM_PIN_FUNCTION(cci_async_in),
+ MSM_PIN_FUNCTION(cci_i2c0),
+ MSM_PIN_FUNCTION(cci_i2c1),
+ MSM_PIN_FUNCTION(cci_i2c2),
+ MSM_PIN_FUNCTION(cci_i2c3),
+ MSM_PIN_FUNCTION(cci_timer),
+ MSM_PIN_FUNCTION(coex_espmi),
+ MSM_PIN_FUNCTION(coex_uart1_rx),
+ MSM_PIN_FUNCTION(coex_uart1_tx),
+ MSM_PIN_FUNCTION(dbg_out_clk),
+ MSM_PIN_FUNCTION(ddr_bist),
+ MSM_PIN_FUNCTION(ddr_pxi),
+ MSM_PIN_FUNCTION(dp_hot),
+ MSM_PIN_FUNCTION(egpio),
+ MSM_PIN_FUNCTION(gcc_gp),
+ MSM_PIN_FUNCTION(gnss_adc),
+ MSM_PIN_FUNCTION(host2wlan_sol),
+ MSM_PIN_FUNCTION(host_rst),
+ MSM_PIN_FUNCTION(i2chub0_se0),
+ MSM_PIN_FUNCTION(i2chub0_se1),
+ MSM_PIN_FUNCTION(i2chub0_se2),
+ MSM_PIN_FUNCTION(i2chub0_se3),
+ MSM_PIN_FUNCTION(i2chub0_se4),
+ MSM_PIN_FUNCTION(i2s0),
+ MSM_PIN_FUNCTION(i2s1),
+ MSM_PIN_FUNCTION(ibi_i3c),
+ MSM_PIN_FUNCTION(ibi_i3c_qup5_se0),
+ MSM_PIN_FUNCTION(jitter_bist),
+ MSM_PIN_FUNCTION(mdp_esync0),
+ MSM_PIN_FUNCTION(mdp_esync1),
+ MSM_PIN_FUNCTION(mdp_esync2),
+ MSM_PIN_FUNCTION(mdp_vsync),
+ MSM_PIN_FUNCTION(mdp_vsync_e),
+ MSM_PIN_FUNCTION(mdp_vsync_p),
+ MSM_PIN_FUNCTION(mdp_vsync0_out),
+ MSM_PIN_FUNCTION(mdp_vsync1_out),
+ MSM_PIN_FUNCTION(mdp_vsync2_out),
+ MSM_PIN_FUNCTION(mdp_vsync3_out),
+ MSM_PIN_FUNCTION(mdp_vsync5_out),
+ MSM_PIN_FUNCTION(modem_pps_in),
+ MSM_PIN_FUNCTION(modem_pps_out),
+ MSM_PIN_FUNCTION(nav_gpio),
+ MSM_PIN_FUNCTION(nav_gpio0),
+ MSM_PIN_FUNCTION(nav_gpio3),
+ MSM_PIN_FUNCTION(nav_rffe),
+ MSM_PIN_FUNCTION(pcie0_clk_req_n),
+ MSM_PIN_FUNCTION(pcie1_clk_req_n),
+ MSM_PIN_FUNCTION(pcie1_rst_n),
+ MSM_PIN_FUNCTION(phase_flag),
+ MSM_PIN_FUNCTION(pll_bist_sync),
+ MSM_PIN_FUNCTION(pll_clk_aux),
+ MSM_PIN_FUNCTION(qdss_cti),
+ MSM_PIN_FUNCTION(qlink),
+ MSM_PIN_FUNCTION(qspi),
+ MSM_PIN_FUNCTION(qspi_clk),
+ MSM_PIN_FUNCTION(qspi_cs),
+ MSM_PIN_FUNCTION(qup1_se0),
+ MSM_PIN_FUNCTION(qup1_se1),
+ MSM_PIN_FUNCTION(qup1_se2),
+ MSM_PIN_FUNCTION(qup1_se3),
+ MSM_PIN_FUNCTION(qup1_se4),
+ MSM_PIN_FUNCTION(qup1_se5),
+ MSM_PIN_FUNCTION(qup1_se6),
+ MSM_PIN_FUNCTION(qup1_se7),
+ MSM_PIN_FUNCTION(qup2_se0),
+ MSM_PIN_FUNCTION(qup2_se1),
+ MSM_PIN_FUNCTION(qup2_se2),
+ MSM_PIN_FUNCTION(qup2_se3),
+ MSM_PIN_FUNCTION(qup2_se4_01),
+ MSM_PIN_FUNCTION(qup2_se4_23),
+ MSM_PIN_FUNCTION(qup3_se0),
+ MSM_PIN_FUNCTION(qup3_se1),
+ MSM_PIN_FUNCTION(qup3_se2),
+ MSM_PIN_FUNCTION(qup3_se3),
+ MSM_PIN_FUNCTION(qup3_se4),
+ MSM_PIN_FUNCTION(qup3_se5),
+ MSM_PIN_FUNCTION(qup4_se0),
+ MSM_PIN_FUNCTION(qup4_se1),
+ MSM_PIN_FUNCTION(qup4_se2),
+ MSM_PIN_FUNCTION(qup4_se3_01),
+ MSM_PIN_FUNCTION(qup4_se3_23),
+ MSM_PIN_FUNCTION(qup4_se3_l3),
+ MSM_PIN_FUNCTION(qup4_se4_01),
+ MSM_PIN_FUNCTION(qup4_se4_23),
+ MSM_PIN_FUNCTION(qup4_se4_l3),
+ MSM_PIN_FUNCTION(qup5_se0),
+ MSM_PIN_FUNCTION(rng_rosc),
+ MSM_PIN_FUNCTION(sd_write_protect),
+ MSM_PIN_FUNCTION(sdc2_clk),
+ MSM_PIN_FUNCTION(sdc2_cmd),
+ MSM_PIN_FUNCTION(sdc2_data),
+ MSM_PIN_FUNCTION(sdc2_rclk),
+ MSM_PIN_FUNCTION(sdc4_clk),
+ MSM_PIN_FUNCTION(sdc4_cmd),
+ MSM_PIN_FUNCTION(sdc4_data),
+ MSM_PIN_FUNCTION(sys_throttle),
+ MSM_PIN_FUNCTION(tb_trig_sdc),
+ MSM_PIN_FUNCTION(tmess_rng),
+ MSM_PIN_FUNCTION(tsense_clm),
+ MSM_PIN_FUNCTION(tsense_pwm),
+ MSM_PIN_FUNCTION(uim0),
+ MSM_PIN_FUNCTION(uim1),
+ MSM_PIN_FUNCTION(usb0_hs),
+ MSM_PIN_FUNCTION(usb_phy),
+ MSM_PIN_FUNCTION(vfr),
+ MSM_PIN_FUNCTION(vsense_trigger_mirnat),
+ MSM_PIN_FUNCTION(wcn_sw),
+};
+
+/* Every pin is maintained as a single group, and missing or non-existing pin
+ * would be maintained as dummy group to synchronize pin group index with
+ * pin descriptor registered with pinctrl core.
+ * Clients would not be able to request these dummy pin groups.
+ */
+static const struct msm_pingroup maili_groups[] = {
+ [0] = PINGROUP(0, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [1] = PINGROUP(1, qup2_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [2] = PINGROUP(2, qup2_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [3] = PINGROUP(3, qup2_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [4] = PINGROUP(4, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [5] = PINGROUP(5, qup2_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [6] = PINGROUP(6, qup2_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [7] = PINGROUP(7, qup2_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [8] = PINGROUP(8, qup3_se1, ibi_i3c, qup5_se0, ibi_i3c_qup5_se0, _, _, _, _, _, _, _),
+ [9] = PINGROUP(9, qup3_se1, ibi_i3c, qup5_se0, ibi_i3c_qup5_se0, _, _, _, _, _, _, _),
+ [10] = PINGROUP(10, qup3_se1, qup5_se0, _, _, _, _, _, _, _, _, _),
+ [11] = PINGROUP(11, qup3_se1, qup5_se0, _, _, _, _, _, _, _, _, _),
+ [12] = PINGROUP(12, qup3_se2, ibi_i3c, qup3_se1, qup5_se0, _, _, _, _, _, _, _),
+ [13] = PINGROUP(13, qup3_se2, ibi_i3c, qup3_se1, qup5_se0, _, _, _, _, _, _, _),
+ [14] = PINGROUP(14, qup3_se2, qup5_se0, _, _, _, _, _, _, _, _, _),
+ [15] = PINGROUP(15, qup3_se2, cci_async_in, qup3_se1, _, _, _, _, _, _, _, _),
+ [16] = PINGROUP(16, qup3_se3, qup5_se0, _, vsense_trigger_mirnat, _, _, _, _, _, _, _),
+ [17] = PINGROUP(17, qup3_se3, qup5_se0, gcc_gp, _, _, _, _, _, _, _, _),
+ [18] = PINGROUP(18, wcn_sw, qup3_se3, _, gnss_adc, _, _, _, _, _, _, _),
+ [19] = PINGROUP(19, wcn_sw, qup3_se3, _, gnss_adc, _, _, _, _, _, _, _),
+ [20] = PINGROUP(20, qup3_se4, _, gnss_adc, _, _, _, _, _, _, _, _),
+ [21] = PINGROUP(21, qup3_se4, _, _, _, _, _, _, _, _, _, _),
+ [22] = PINGROUP(22, qup3_se4, _, _, _, _, _, _, _, _, _, _),
+ [23] = PINGROUP(23, qup3_se4, _, gnss_adc, _, _, _, _, _, _, _, _),
+ [24] = PINGROUP(24, qup3_se5, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [25] = PINGROUP(25, qup3_se5, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [26] = PINGROUP(26, qup3_se5, _, _, _, _, _, _, _, _, _, _),
+ [27] = PINGROUP(27, qup3_se5, _, _, _, _, _, _, _, _, _, _),
+ [28] = PINGROUP(28, qup4_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [29] = PINGROUP(29, qup4_se1, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [30] = PINGROUP(30, qup4_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [31] = PINGROUP(31, qup4_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [32] = PINGROUP(32, qup4_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [33] = PINGROUP(33, qup4_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [34] = PINGROUP(34, qup4_se2, _, _, _, _, _, _, _, _, _, _),
+ [35] = PINGROUP(35, qup4_se2, tsense_pwm, _, _, _, _, _, _, _, _, _),
+ [36] = PINGROUP(36, qup1_se4, uim1, ibi_i3c, _, _, _, _, _, _, _, _),
+ [37] = PINGROUP(37, qup1_se4, uim1, ibi_i3c, _, _, _, _, _, _, _, _),
+ [38] = PINGROUP(38, qup1_se4, tsense_pwm, _, _, _, _, _, _, _, _, _),
+ [39] = PINGROUP(39, qup1_se4, uim1, _, _, _, _, _, _, _, _, _),
+ [40] = PINGROUP(40, qup1_se2, ddr_bist, phase_flag, _, _, _, _, _, _, _, _),
+ [41] = PINGROUP(41, qup1_se2, ddr_bist, phase_flag, _, _, _, _, _, _, _, _),
+ [42] = PINGROUP(42, qup1_se2, _, _, _, _, _, _, _, _, _, _),
+ [43] = PINGROUP(43, qup1_se2, _, _, _, _, _, _, _, _, _, _),
+ [44] = PINGROUP(44, qup1_se3, ddr_bist, phase_flag, _, _, _, _, _, _, _, _),
+ [45] = PINGROUP(45, qup1_se3, ddr_bist, phase_flag, _, _, _, _, _, _, _, _),
+ [46] = PINGROUP(46, qup1_se3, i2s0, phase_flag, _, _, _, _, _, _, _, _),
+ [47] = PINGROUP(47, qup1_se3, dp_hot, phase_flag, _, _, _, _, _, _, _, _),
+ [48] = PINGROUP(48, qup4_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [49] = PINGROUP(49, qup4_se0, ibi_i3c, _, _, _, _, _, _, _, _, egpio),
+ [50] = PINGROUP(50, qup4_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [51] = PINGROUP(51, qup4_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [52] = PINGROUP(52, qup1_se5, _, _, _, _, _, _, _, _, _, _),
+ [53] = PINGROUP(53, qup1_se5, _, _, _, _, _, _, _, _, _, _),
+ [54] = PINGROUP(54, qup1_se5, uim1, sdc2_rclk, _, _, _, _, _, _, _, _),
+ [55] = PINGROUP(55, qup1_se5, uim1, _, _, _, _, _, _, _, _, _),
+ [56] = PINGROUP(56, qup1_se6, uim1, sdc2_clk, _, _, _, _, _, _, _, _),
+ [57] = PINGROUP(57, qup1_se6, sdc2_cmd, _, _, _, _, _, _, _, _, _),
+ [58] = PINGROUP(58, qup1_se6, tsense_pwm, _, _, _, _, _, _, _, _, _),
+ [59] = PINGROUP(59, qup1_se6, usb_phy, _, _, _, _, _, _, _, _, _),
+ [60] = PINGROUP(60, qup1_se7, usb_phy, ibi_i3c, _, _, _, _, _, _, _, _),
+ [61] = PINGROUP(61, qup1_se7, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [62] = PINGROUP(62, qup1_se7, _, _, _, _, _, _, _, _, _, _),
+ [63] = PINGROUP(63, qup1_se7, _, _, _, _, _, _, _, _, _, _),
+ [64] = PINGROUP(64, qup3_se0, rng_rosc, tmess_rng, ibi_i3c, _, _, _, _, _, _, _),
+ [65] = PINGROUP(65, qup3_se0, rng_rosc, tmess_rng, ibi_i3c, _, _, _, _, _, _, _),
+ [66] = PINGROUP(66, i2chub0_se0, qup3_se0, rng_rosc, tmess_rng, _, ddr_pxi, _, _, _, _, _),
+ [67] = PINGROUP(67, i2chub0_se0, qup3_se0, _, ddr_pxi, _, _, _, _, _, _, _),
+ [68] = PINGROUP(68, i2chub0_se2, _, ddr_pxi, _, _, _, _, _, _, _, _),
+ [69] = PINGROUP(69, i2chub0_se2, _, ddr_pxi, _, _, _, _, _, _, _, _),
+ [70] = PINGROUP(70, i2chub0_se3, uim1, _, _, ddr_pxi, _, _, _, _, _, _),
+ [71] = PINGROUP(71, i2chub0_se3, uim1, _, _, ddr_pxi, _, _, _, _, _, _),
+ [72] = PINGROUP(72, i2chub0_se4, uim1, qdss_cti, _, ddr_pxi, _, _, _, _, _, _),
+ [73] = PINGROUP(73, i2chub0_se4, qdss_cti, jitter_bist, ddr_pxi, _, _, _, _, _, _, _),
+ [74] = PINGROUP(74, qup1_se1, aoss_cti, sdc2_data, _, _, _, _, _, _, _, _),
+ [75] = PINGROUP(75, qup1_se1, aoss_cti, sdc2_data, _, _, _, _, _, _, _, _),
+ [76] = PINGROUP(76, qup1_se1, aoss_cti, sdc2_data, _, _, _, _, _, _, _, _),
+ [77] = PINGROUP(77, qup1_se1, aoss_cti, sdc2_data, _, _, _, _, _, _, _, _),
+ [78] = PINGROUP(78, i2chub0_se1, _, atest_usb, _, _, _, _, _, _, _, _),
+ [79] = PINGROUP(79, i2chub0_se1, usb0_hs, _, atest_usb, _, _, _, _, _, _, _),
+ [80] = PINGROUP(80, sdc4_data, qspi, _, _, _, _, _, _, _, _, _),
+ [81] = PINGROUP(81, sdc4_data, qspi, _, _, _, _, _, _, _, _, _),
+ [82] = PINGROUP(82, sdc4_data, qdss_cti, qspi, qup3_se0, dbg_out_clk, _, _, _, _, _, _),
+ [83] = PINGROUP(83, sdc4_clk, qdss_cti, qspi_clk, qup3_se0, _, _, _, _, _, _, _),
+ [84] = PINGROUP(84, qup4_se3_01, qup4_se3_23, rng_rosc, tmess_rng, i2s0, _, _, _, _, _, _),
+ [85] = PINGROUP(85, sd_write_protect, qup5_se0, ibi_i3c, _, _, _, _, _, _, _, _),
+ [86] = PINGROUP(86, mdp_vsync, mdp_vsync0_out, mdp_vsync1_out, mdp_esync1, gcc_gp,
+ _, _, _, _, _, _),
+ [87] = PINGROUP(87, mdp_vsync, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out, mdp_esync2,
+ gcc_gp, tsense_clm, tsense_pwm, _, _, _),
+ [88] = PINGROUP(88, mdp_esync0, mdp_vsync, qup4_se4_l3, tb_trig_sdc, _, _, _, _, _, _, _),
+ [89] = PINGROUP(89, qup5_se0, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [90] = PINGROUP(90, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [91] = PINGROUP(91, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [92] = PINGROUP(92, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [93] = PINGROUP(93, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [94] = PINGROUP(94, cam_mclk, pll_clk_aux, _, _, _, _, _, _, _, _, _),
+ [95] = PINGROUP(95, cam_mclk, _, _, _, _, _, _, _, _, _, _),
+ [96] = PINGROUP(96, _, _, _, _, _, _, _, _, _, _, _),
+ [97] = PINGROUP(97, mdp_esync2, qup2_se3, mdp_vsync, gcc_gp, tsense_clm, tsense_pwm,
+ _, _, _, _, _),
+ [98] = PINGROUP(98, mdp_vsync_e, qup4_se3_l3, mdp_vsync_p, tsense_clm, tsense_pwm,
+ _, _, _, _, _, _),
+ [99] = PINGROUP(99, sys_throttle, tsense_clm, tsense_pwm, _, _, _, _, _, _, _, _),
+ [100] = PINGROUP(100, mdp_esync1, mdp_esync0, qup5_se0, _, _, _, _, _, _, _, _),
+ [101] = PINGROUP(101, _, _, _, _, _, _, _, _, _, _, _),
+ [102] = PINGROUP(102, atest_usb, _, _, _, _, _, _, _, _, _, _),
+ [103] = PINGROUP(103, pcie0_clk_req_n, atest_usb, _, _, _, _, _, _, _, _, _),
+ [104] = PINGROUP(104, pll_bist_sync, atest_usb, _, _, _, _, _, _, _, _, _),
+ [105] = PINGROUP(105, cci_timer, tsense_clm, _, _, _, _, _, _, _, _, _),
+ [106] = PINGROUP(106, host_rst, cci_timer, tsense_clm, _, _, _, _, _, _, _, _),
+ [107] = PINGROUP(107, cci_i2c3, cci_timer, _, _, _, _, _, _, _, _, _),
+ [108] = PINGROUP(108, _, _, _, _, _, _, _, _, _, _, _),
+ [109] = PINGROUP(109, cci_i2c0, cci_async_in, _, _, _, _, _, _, _, _, _),
+ [110] = PINGROUP(110, cci_i2c0, cci_async_in, _, _, _, _, _, _, _, _, _),
+ [111] = PINGROUP(111, cci_i2c1, _, _, _, _, _, _, _, _, _, _),
+ [112] = PINGROUP(112, cci_i2c1, _, _, _, _, _, _, _, _, _, _),
+ [113] = PINGROUP(113, cci_i2c2, _, _, _, _, _, _, _, _, _, _),
+ [114] = PINGROUP(114, cci_i2c2, _, _, _, _, _, _, _, _, _, _),
+ [115] = PINGROUP(115, _, _, _, _, _, _, _, _, _, _, _),
+ [116] = PINGROUP(116, _, _, _, _, _, _, _, _, _, _, _),
+ [117] = PINGROUP(117, qup2_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [118] = PINGROUP(118, qup2_se2, ibi_i3c, _, _, _, _, _, _, _, _, _),
+ [119] = PINGROUP(119, qup2_se2, _, _, _, _, _, _, _, _, _, _),
+ [120] = PINGROUP(120, qup2_se2, audio_ext_mclk, audio_ref_clk, _, _, _, _, _, _, _, _),
+ [121] = PINGROUP(121, audio_ext_mclk, qup4_se3_01, qup4_se3_23, _, _, _, _, _, _, _, _),
+ [122] = PINGROUP(122, qup2_se3, _, _, _, _, _, _, _, _, _, _),
+ [123] = PINGROUP(123, qup2_se3, _, _, _, _, _, _, _, _, _, _),
+ [124] = PINGROUP(124, qup2_se3, _, _, _, _, _, _, _, _, _, _),
+ [125] = PINGROUP(125, qup2_se3, _, _, _, _, _, _, _, _, _, _),
+ [126] = PINGROUP(126, uim0, phase_flag, _, atest_char, _, _, _, _, _, _, _),
+ [127] = PINGROUP(127, uim0, phase_flag, _, atest_char, _, _, _, _, _, _, _),
+ [128] = PINGROUP(128, uim0, phase_flag, _, atest_char, _, _, _, _, _, _, _),
+ [129] = PINGROUP(129, uim0, phase_flag, _, atest_char, _, _, _, _, _, _, _),
+ [130] = PINGROUP(130, uim1, qup1_se2, _, phase_flag, _, _, _, _, _, _, _),
+ [131] = PINGROUP(131, uim1, qup1_se2, _, phase_flag, _, _, _, _, _, _, _),
+ [132] = PINGROUP(132, uim1, qup1_se2, _, phase_flag, _, _, _, _, _, _, _),
+ [133] = PINGROUP(133, uim1, phase_flag, _, atest_char, _, _, _, _, _, _, _),
+ [134] = PINGROUP(134, _, _, nav_rffe, _, _, _, _, _, _, _, _),
+ [135] = PINGROUP(135, _, _, nav_rffe, _, _, _, _, _, _, _, _),
+ [136] = PINGROUP(136, _, _, _, _, _, _, _, _, _, _, _),
+ [137] = PINGROUP(137, _, _, _, _, _, _, _, _, _, _, _),
+ [138] = PINGROUP(138, _, _, nav_rffe, _, _, _, _, _, _, _, _),
+ [139] = PINGROUP(139, _, _, nav_rffe, _, _, _, _, _, _, _, _),
+ [140] = PINGROUP(140, _, _, _, _, _, _, _, _, _, _, _),
+ [141] = PINGROUP(141, _, _, _, _, _, _, _, _, _, _, _),
+ [142] = PINGROUP(142, _, _, _, _, _, _, _, _, _, _, _),
+ [143] = PINGROUP(143, _, _, _, _, _, _, _, _, _, _, _),
+ [144] = PINGROUP(144, coex_uart1_rx, coex_espmi, _, _, _, _, _, _, _, _, _),
+ [145] = PINGROUP(145, coex_uart1_tx, coex_espmi, _, _, _, _, _, _, _, _, _),
+ [146] = PINGROUP(146, _, vfr, nav_gpio, tb_trig_sdc, qspi_cs, _, _, _, _, _, _),
+ [147] = PINGROUP(147, _, nav_gpio, sdc4_data, qspi, _, _, _, _, _, _, _),
+ [148] = PINGROUP(148, nav_gpio, _, sdc4_cmd, qspi_cs, _, _, _, _, _, _, _),
+ [149] = PINGROUP(149, _, _, _, _, _, _, _, _, _, _, _),
+ [150] = PINGROUP(150, nav_gpio0, nav_gpio3, _, _, _, _, _, _, _, _, _),
+ [151] = PINGROUP(151, nav_gpio, vfr, modem_pps_in, modem_pps_out, _, _, _, _, _, _, _),
+ [152] = PINGROUP(152, qlink, _, _, _, _, _, _, _, _, _, _),
+ [153] = PINGROUP(153, qlink, _, _, _, _, _, _, _, _, _, _),
+ [154] = PINGROUP(154, qlink, _, _, _, _, _, _, _, _, _, _),
+ [155] = PINGROUP(155, wcn_sw, gcc_gp, _, _, _, _, _, _, _, _, _),
+ [156] = PINGROUP(156, wcn_sw, gcc_gp, _, _, _, _, _, _, _, _, _),
+ [157] = PINGROUP(157, _, _, _, _, _, _, _, _, _, _, _),
+ [158] = PINGROUP(158, _, _, _, _, _, _, _, _, _, _, _),
+ [159] = PINGROUP(159, cci_timer, tsense_clm, _, _, _, _, _, _, _, _, _),
+ [160] = PINGROUP(160, cci_timer, cci_i2c3, _, _, _, _, _, _, _, _, _),
+ [161] = PINGROUP(161, qup4_se4_01, qup4_se4_23, i2s0, phase_flag, _, _, _, _, _, _, _),
+ [162] = PINGROUP(162, qup4_se4_01, qup4_se4_23, i2s0, phase_flag, _, _, _, _, _, _, _),
+ [163] = PINGROUP(163, _, _, _, _, _, _, _, _, _, _, egpio),
+ [164] = PINGROUP(164, _, _, _, _, _, _, _, _, _, _, egpio),
+ [165] = PINGROUP(165, _, _, _, _, _, _, _, _, _, _, egpio),
+ [166] = PINGROUP(166, _, _, _, _, _, _, _, _, _, _, egpio),
+ [167] = PINGROUP(167, _, _, _, _, _, _, _, _, _, _, egpio),
+ [168] = PINGROUP(168, _, _, _, _, _, _, _, _, _, _, egpio),
+ [169] = PINGROUP(169, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [170] = PINGROUP(170, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [171] = PINGROUP(171, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [172] = PINGROUP(172, _, _, _, _, _, _, _, _, _, _, egpio),
+ [173] = PINGROUP(173, _, _, _, _, _, _, _, _, _, _, egpio),
+ [174] = PINGROUP(174, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [175] = PINGROUP(175, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [176] = PINGROUP(176, _, _, _, _, _, _, _, _, _, _, egpio),
+ [177] = PINGROUP(177, _, _, _, _, _, _, _, _, _, _, egpio),
+ [178] = PINGROUP(178, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [179] = PINGROUP(179, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [180] = PINGROUP(180, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [181] = PINGROUP(181, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [182] = PINGROUP(182, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [183] = PINGROUP(183, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [184] = PINGROUP(184, _, _, _, _, _, _, _, _, _, _, egpio),
+ [185] = PINGROUP(185, _, _, _, _, _, _, _, _, _, _, egpio),
+ [186] = PINGROUP(186, _, _, _, _, _, _, _, _, _, _, egpio),
+ [187] = PINGROUP(187, _, _, _, _, _, _, _, _, _, _, egpio),
+ [188] = PINGROUP(188, qup1_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [189] = PINGROUP(189, qup1_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [190] = PINGROUP(190, _, _, _, _, _, _, _, _, _, _, egpio),
+ [191] = PINGROUP(191, _, _, _, _, _, _, _, _, _, _, egpio),
+ [192] = PINGROUP(192, qup1_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [193] = PINGROUP(193, qup1_se1, _, _, _, _, _, _, _, _, _, egpio),
+ [194] = PINGROUP(194, _, _, _, _, _, _, _, _, _, _, egpio),
+ [195] = PINGROUP(195, _, _, _, _, _, _, _, _, _, _, egpio),
+ [196] = PINGROUP(196, _, _, _, _, _, _, _, _, _, _, egpio),
+ [197] = PINGROUP(197, _, _, _, _, _, _, _, _, _, _, egpio),
+ [198] = PINGROUP(198, _, _, _, _, _, _, _, _, _, _, egpio),
+ [199] = PINGROUP(199, _, _, _, _, _, _, _, _, _, _, egpio),
+ [200] = PINGROUP(200, _, _, _, _, _, _, _, _, _, _, egpio),
+ [201] = PINGROUP(201, _, _, _, _, _, _, _, _, _, _, egpio),
+ [202] = PINGROUP(202, _, _, _, _, _, _, _, _, _, _, egpio),
+ [203] = PINGROUP(203, _, _, _, _, _, _, _, _, _, _, egpio),
+ [204] = PINGROUP(204, host2wlan_sol, _, _, _, _, _, _, _, _, _, egpio),
+ [205] = PINGROUP(205, phase_flag, _, _, _, _, _, _, _, _, _, egpio),
+ [206] = PINGROUP(206, _, _, _, _, _, _, _, _, _, _, egpio),
+ [207] = PINGROUP(207, _, _, _, _, _, _, _, _, _, _, egpio),
+ [208] = PINGROUP(208, qup2_se4_01, qup2_se4_23, _, _, _, _, _, _, _, _, egpio),
+ [209] = PINGROUP(209, qup2_se4_01, qup2_se4_23, _, _, _, _, _, _, _, _, egpio),
+ [210] = PINGROUP(210, _, _, _, _, _, _, _, _, _, _, _),
+ [211] = PINGROUP(211, _, _, _, _, _, _, _, _, _, _, _),
+ [212] = PINGROUP(212, _, _, _, _, _, _, _, _, _, _, egpio),
+ [213] = PINGROUP(213, _, _, _, _, _, _, _, _, _, _, egpio),
+ [214] = PINGROUP(214, qup5_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [215] = PINGROUP(215, qup5_se0, _, _, _, _, _, _, _, _, _, egpio),
+ [216] = PINGROUP(216, _, _, _, _, _, _, _, _, _, _, egpio),
+ [217] = PINGROUP(217, _, _, _, _, _, _, _, _, _, _, egpio),
+ [218] = PINGROUP(218, _, _, _, _, _, _, _, _, _, _, egpio),
+ [219] = PINGROUP(219, _, _, _, _, _, _, _, _, _, _, _),
+ [220] = PINGROUP(220, pcie1_rst_n, _, _, _, _, _, _, _, _, _, _),
+ [221] = PINGROUP(221, pcie1_clk_req_n, _, _, _, _, _, _, _, _, _, _),
+ [222] = PINGROUP(222, qup1_se0, i2s1, qdss_cti, phase_flag, _, _, _, _, _, _, _),
+ [223] = PINGROUP(223, qup1_se0, i2s1, qdss_cti, phase_flag, _, _, _, _, _, _, _),
+ [224] = PINGROUP(224, qup1_se0, i2s1, qdss_cti, phase_flag, _, _, _, _, _, _, _),
+ [225] = PINGROUP(225, qup1_se0, i2s1, qdss_cti, phase_flag, _, _, _, _, _, _, _),
+ [226] = UFS_RESET(ufs_reset, 0xf1004, 0xf2000),
+ [227] = SDC_QDSD_PINGROUP(sdc2_clk, 0xe6000, 14, 6),
+ [228] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xe6000, 11, 3),
+ [229] = SDC_QDSD_PINGROUP(sdc2_data, 0xe6000, 9, 0),
+};
+
+static const struct msm_gpio_wakeirq_map maili_pdc_map[] = {
+ { 0, 111 }, { 3, 119 }, { 4, 112 }, { 7, 113 }, { 8, 114 }, { 11, 115 },
+ { 12, 121 }, { 15, 137 }, { 16, 122 }, { 17, 147 }, { 18, 149 }, { 19, 118 },
+ { 23, 123 }, { 24, 124 }, { 27, 125 }, { 28, 131 }, { 31, 132 }, { 32, 133 },
+ { 35, 107 }, { 36, 134 }, { 39, 135 }, { 43, 136 }, { 47, 160 }, { 48, 141 },
+ { 51, 120 }, { 55, 110 }, { 57, 142 }, { 58, 143 }, { 59, 144 }, { 60, 145 },
+ { 61, 151 }, { 63, 130 }, { 64, 116 }, { 65, 129 }, { 67, 138 }, { 68, 152 },
+ { 69, 153 }, { 75, 157 }, { 77, 154 }, { 78, 155 }, { 79, 161 }, { 80, 162 },
+ { 81, 163 }, { 82, 164 }, { 83, 171 }, { 84, 140 }, { 85, 165 }, { 86, 166 },
+ { 87, 167 }, { 88, 168 }, { 95, 169 }, { 96, 170 }, { 97, 139 }, { 98, 156 },
+ { 99, 117 }, { 100, 199 }, { 103, 173 }, { 104, 174 }, { 117, 201 }, { 120, 175 },
+ { 123, 176 }, { 125, 177 }, { 129, 159 }, { 133, 106 }, { 144, 178 }, { 146, 179 },
+ { 151, 180 }, { 152, 181 }, { 155, 128 }, { 158, 126 }, { 162, 148 }, { 164, 182 },
+ { 165, 183 }, { 167, 184 }, { 168, 185 }, { 174, 186 }, { 177, 187 }, { 179, 188 },
+ { 183, 189 }, { 184, 190 }, { 185, 191 }, { 186, 158 }, { 188, 150 }, { 202, 108 },
+ { 203, 109 }, { 205, 146 }, { 209, 192 }, { 213, 127 }, { 215, 200 }, { 216, 193 },
+ { 220, 172 }, { 221, 194 }, { 222, 195 }, { 223, 196 }, { 224, 197 }, { 225, 198 },
+};
+
+static const struct msm_pinctrl_soc_data maili_tlmm = {
+ .pins = maili_pins,
+ .npins = ARRAY_SIZE(maili_pins),
+ .functions = maili_functions,
+ .nfunctions = ARRAY_SIZE(maili_functions),
+ .groups = maili_groups,
+ .ngroups = ARRAY_SIZE(maili_groups),
+ .ngpios = 227,
+ .wakeirq_map = maili_pdc_map,
+ .nwakeirq_map = ARRAY_SIZE(maili_pdc_map),
+ .egpio_func = 11,
+};
+
+static const struct of_device_id maili_tlmm_of_match[] = {
+ { .compatible = "qcom,maili-tlmm", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, maili_tlmm_of_match);
+
+static int maili_tlmm_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &maili_tlmm);
+}
+
+static struct platform_driver maili_tlmm_driver = {
+ .driver = {
+ .name = "maili-tlmm",
+ .of_match_table = maili_tlmm_of_match,
+ },
+ .probe = maili_tlmm_probe,
+};
+
+static int __init maili_tlmm_init(void)
+{
+ return platform_driver_register(&maili_tlmm_driver);
+}
+arch_initcall(maili_tlmm_init);
+
+static void __exit maili_tlmm_exit(void)
+{
+ platform_driver_unregister(&maili_tlmm_driver);
+}
+module_exit(maili_tlmm_exit);
+
+MODULE_DESCRIPTION("Qualcomm Maili TLMM driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: pinctrl: qcom: Describe Maili TLMM block
From: Jingyi Wang @ 2026-06-15 6:55 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: aiqun.yu, tingwei.zhang, trilok.soni, yijie.yang, linux-arm-msm,
linux-gpio, devicetree, linux-kernel, Jingyi Wang,
Krzysztof Kozlowski
In-Reply-To: <20260614-maili-pinctrl-v2-0-0db5bfc23d64@oss.qualcomm.com>
The Top Level Mode Multiplexer (TLMM) in the Qualcomm Maili SoC provides
GPIO and pinctrl functionality for UFS, SDC and 226 GPIO pins.
Add a DeviceTree binding to describe the TLMM block on Qualcomm's Maili
SoC.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
---
.../bindings/pinctrl/qcom,maili-tlmm.yaml | 120 +++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,maili-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,maili-tlmm.yaml
new file mode 100644
index 000000000000..64fe90b2391b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,maili-tlmm.yaml
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,maili-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. Maili TLMM block
+
+maintainers:
+ - Jingyi Wang <jingyi.wang@oss.qualcomm.com>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm Maili SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,maili-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 113
+
+ gpio-line-names:
+ maxItems: 226
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-maili-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-maili-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-maili-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+ unevaluatedProperties: false
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-9][0-9]|20[0-9]|21[0-9]|22[0-5])$"
+ - enum: [ ufs_reset, sdc2_clk, sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+ enum: [ gpio, aoss_cti, atest_char, atest_usb, audio_ext_mclk,
+ audio_ref_clk, cam_mclk, cci_async_in, cci_i2c0, cci_i2c1,
+ cci_i2c2, cci_i2c3, cci_timer, coex_espmi, coex_uart1_rx,
+ coex_uart1_tx, dbg_out_clk, ddr_bist, ddr_pxi, dp_hot, egpio,
+ gcc_gp, gnss_adc, host2wlan_sol, host_rst, i2chub0_se0,
+ i2chub0_se1, i2chub0_se2, i2chub0_se3, i2chub0_se4, i2s0, i2s1,
+ ibi_i3c, ibi_i3c_qup5_se0, jitter_bist, mdp_esync0, mdp_esync1,
+ mdp_esync2, mdp_vsync, mdp_vsync_e, mdp_vsync_p, mdp_vsync0_out,
+ mdp_vsync1_out, mdp_vsync2_out, mdp_vsync3_out, mdp_vsync5_out,
+ modem_pps_in, modem_pps_out, nav_gpio, nav_gpio0, nav_gpio3,
+ nav_rffe, pcie0_clk_req_n, pcie1_clk_req_n, pcie1_rst_n,
+ phase_flag, pll_bist_sync, pll_clk_aux, qdss_cti, qlink, qspi,
+ qspi_clk, qspi_cs, qup1_se0, qup1_se1, qup1_se2, qup1_se3,
+ qup1_se4, qup1_se5, qup1_se6, qup1_se7, qup2_se0, qup2_se1,
+ qup2_se2, qup2_se3, qup2_se4_01, qup2_se4_23, qup3_se0,
+ qup3_se1, qup3_se2, qup3_se3, qup3_se4, qup3_se5, qup4_se0,
+ qup4_se1, qup4_se2, qup4_se3_01, qup4_se3_23, qup4_se3_l3,
+ qup4_se4_01, qup4_se4_23, qup4_se4_l3, qup5_se0, rng_rosc,
+ sd_write_protect, sdc2_clk, sdc2_cmd, sdc2_data, sdc2_rclk,
+ sdc4_clk, sdc4_cmd, sdc4_data, sys_throttle, tb_trig_sdc,
+ tmess_rng, tsense_clm, tsense_pwm, uim0, uim1, usb0_hs, usb_phy,
+ vfr, vsense_trigger_mirnat, wcn_sw ]
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@f100000 {
+ compatible = "qcom,maili-tlmm";
+ reg = <0x0f100000 0x300000>;
+ interrupts = <GIC_ESPI 272 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 227>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ qup-uart7-state {
+ pins = "gpio62", "gpio63";
+ function = "qup1_se7";
+ };
+ };
+...
--
2.34.1
^ permalink raw reply related
* [PATCH v2 0/2] pinctrl: qcom: Introduce Pinctrl for the upcoming Maili SoC
From: Jingyi Wang @ 2026-06-15 6:55 UTC (permalink / raw)
To: Bjorn Andersson, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: aiqun.yu, tingwei.zhang, trilok.soni, yijie.yang, linux-arm-msm,
linux-gpio, devicetree, linux-kernel, Jingyi Wang,
Krzysztof Kozlowski
Introduce Top Level Mode Multiplexer dt-binding and driver for the
upcoming Qualcomm Maili SoC. Maili is the new mobile SoC, and its DTS
will be upstreamed later.
Signed-off-by: Jingyi Wang <jingyi.wang@oss.qualcomm.com>
---
Changes in v2:
- Move MODULE_DEVICE_TABLE next to the table itself
- Update gpio function to MSM_GPIO_PIN_FUNCTION
- Link to v1: https://lore.kernel.org/r/20260522-maili-pinctrl-v1-0-0a6636f5c277@oss.qualcomm.com
---
Jingyi Wang (2):
dt-bindings: pinctrl: qcom: Describe Maili TLMM block
pinctrl: qcom: Add the tlmm driver for Maili platform
.../bindings/pinctrl/qcom,maili-tlmm.yaml | 120 ++
drivers/pinctrl/qcom/Kconfig.msm | 10 +
drivers/pinctrl/qcom/Makefile | 1 +
drivers/pinctrl/qcom/pinctrl-maili.c | 1630 ++++++++++++++++++++
4 files changed, 1761 insertions(+)
---
base-commit: c425609d6ac4012c8bbf01ec2e10e801b1923a7b
change-id: 20260614-maili-pinctrl-230a8ce90bcd
Best regards,
--
Jingyi Wang <jingyi.wang@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH] dt-bindings: spi: microchip,pic32: Convert to DT schema
From: Krzysztof Kozlowski @ 2026-06-15 6:53 UTC (permalink / raw)
To: Udaya Kiran Challa
Cc: tsbogend, robh, krzk+dt, conor+dt, skhan, me, linux-rtc,
devicetree, linux-kernel
In-Reply-To: <20260614175005.435826-1-challauday369@gmail.com>
On Sun, Jun 14, 2026 at 11:20:05PM +0530, Udaya Kiran Challa wrote:
> Convert Microchip PIC32 SPI controller devicetree binding
> from legacy text format to DT schema.
>
> Signed-off-by: Udaya Kiran Challa <challauday369@gmail.com>
> ---
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
spi: dt-bindings:
> .../bindings/spi/microchip,pic32-spi.yaml | 78 +++++++++++++++++++
> .../bindings/spi/microchip,spi-pic32.txt | 34 --------
> 2 files changed, 78 insertions(+), 34 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/spi/microchip,pic32-spi.yaml
Use compatible as filename (and don't forget to test binding after
renaming).
Rest looks good, so with these two changed:
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH v4 6/6] drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
From: Joey Lu @ 2026-06-15 6:50 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260615065003.76661-1-a0987203069@gmail.com>
The DCUltraLite hardware ops and HWDB entry added in the preceding commits
enable the driver to work on Nuvoton MA35D1 hardware. Allow the driver
to be built when ARCH_MA35 is selected; this dependency is meaningful only
now that all supporting code is in place.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/verisilicon/Kconfig b/drivers/gpu/drm/verisilicon/Kconfig
index 7cce86ec8603..295d246eb4b4 100644
--- a/drivers/gpu/drm/verisilicon/Kconfig
+++ b/drivers/gpu/drm/verisilicon/Kconfig
@@ -2,7 +2,7 @@
config DRM_VERISILICON_DC
tristate "DRM Support for Verisilicon DC-series display controllers"
depends on DRM && COMMON_CLK
- depends on RISCV || COMPILE_TEST
+ depends on RISCV || ARCH_MA35 || COMPILE_TEST
select DRM_BRIDGE_CONNECTOR
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_HELPER
--
2.43.0
^ permalink raw reply related
* [PATCH v4 5/6] drm/verisilicon: add DCUltraLite chip identity to HWDB
From: Joey Lu @ 2026-06-15 6:50 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260615065003.76661-1-a0987203069@gmail.com>
Register the Nuvoton MA35D1 DCUltraLite chip identity in
vs_chip_identities[]:
model = 0x0 (DCUltraLite; Verisilicon uses 0 for this IP)
revision = 0x5560
customer_id = 0x305
generation = VSDC_GEN_DC8000
display_count = 1
max_cursor_size = 32
Placing this entry last makes it the gate that enables MA35D1 hardware
recognition only after all the supporting ops and DT binding changes are
in place.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_hwdb.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 91524d16f778..7d630a667a3f 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -129,6 +129,16 @@ static struct vs_chip_identity vs_chip_identities[] = {
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
},
+ {
+ .model = 0x0, /* DCUltraLite */
+ .revision = 0x5560,
+ .customer_id = 0x305,
+
+ .generation = VSDC_GEN_DC8000,
+ .display_count = 1,
+ .max_cursor_size = 32,
+ .formats = &vs_formats_no_yuv444,
+ },
};
int vs_fill_chip_identity(struct regmap *regs,
--
2.43.0
^ permalink raw reply related
* [PATCH v4 4/6] drm/verisilicon: add DC8000 (DCUltraLite) display controller support
From: Joey Lu @ 2026-06-15 6:50 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260615065003.76661-1-a0987203069@gmail.com>
The Nuvoton MA35D1 SoC integrates a Verisilicon DCUltraLite display
controller whose register layout differs from the DC8200 in several
important ways:
1. No CONFIG_EX commit path: framebuffer updates use the enable (bit 0)
and reset (bit 4) bits in FB_CONFIG instead of the DC8200 staging
registers (FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT,
FB_BLEND_CONFIG, PANEL_CONFIG_EX).
2. No PANEL_START register: panel output starts when
PANEL_CONFIG.RUNNING is set; there is no multi-display sync start
register.
3. Different IRQ registers: DCUltraLite uses DISP_IRQ_STA (0x147C) /
DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
TOP_IRQ_EN (0x0014).
4. Per-frame commit cycle: DCUltraLite requires the VALID bit in
FB_CONFIG to be set at the start of each atomic commit (crtc_begin)
and cleared after (crtc_flush).
5. Simpler clock topology: only 'core' (bus gate) and 'pix0' (pixel
divider) clocks; no axi or ahb clocks required. Make axi_clk and
ahb_clk optional (devm_clk_get_optional_enabled) so DC8000 nodes
without those clocks are handled gracefully.
Add vs_dc8000.c implementing the vs_dc_funcs vtable for the above
differences. The probe now selects vs_dc8000_funcs when the identified
generation is VSDC_GEN_DC8000 (DCUltraLite reads model 0x0,
revision 0x5560, customer_id 0x305).
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_dc.c | 9 ++-
drivers/gpu/drm/verisilicon/vs_dc.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc8000.c | 78 +++++++++++++++++++++++++
4 files changed, 86 insertions(+), 4 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 9d4cd16452fa..d2fd8e4dff24 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_dc8000.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index 9729b693d360..9499fffbca58 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->core_clk);
}
- dc->axi_clk = devm_clk_get_enabled(dev, "axi");
+ dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
if (IS_ERR(dc->axi_clk)) {
dev_err(dev, "can't get axi clock\n");
return PTR_ERR(dc->axi_clk);
}
- dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
+ dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
if (IS_ERR(dc->ahb_clk)) {
dev_err(dev, "can't get ahb clock\n");
return PTR_ERR(dc->ahb_clk);
@@ -134,7 +134,10 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
- dc->funcs = &vs_dc8200_funcs;
+ if (dc->identity.generation == VSDC_GEN_DC8200)
+ dc->funcs = &vs_dc8200_funcs;
+ else
+ dc->funcs = &vs_dc8000_funcs;
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index 544e1a37065b..5218e8cf63e2 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -66,5 +66,6 @@ struct vs_dc {
};
extern const struct vs_dc_funcs vs_dc8200_funcs;
+extern const struct vs_dc_funcs vs_dc8000_funcs;
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8000.c b/drivers/gpu/drm/verisilicon/vs_dc8000.c
new file mode 100644
index 000000000000..be0c0d7baf52
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8000.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_crtc_regs.h"
+#include "vs_dc.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8000_panel_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dc8000_panel_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dc8000_crtc_begin(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dc8000_crtc_flush(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dc8000_crtc_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dc8000_crtc_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dc8000_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8000_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static u32 vs_dc8000_irq_ack(struct vs_dc *dc)
+{
+ u32 irqs;
+
+ regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &irqs);
+ return irqs;
+}
+
+const struct vs_dc_funcs vs_dc8000_funcs = {
+ .panel_enable_ex = vs_dc8000_panel_enable_ex,
+ .panel_disable_ex = vs_dc8000_panel_disable_ex,
+ .crtc_begin = vs_dc8000_crtc_begin,
+ .crtc_flush = vs_dc8000_crtc_flush,
+ .crtc_enable = vs_dc8000_crtc_enable,
+ .crtc_disable = vs_dc8000_crtc_disable,
+ .enable_vblank = vs_dc8000_enable_vblank,
+ .disable_vblank = vs_dc8000_disable_vblank,
+ .irq_ack = vs_dc8000_irq_ack,
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v4 3/6] drm/verisilicon: introduce per-variant hardware ops table
From: Joey Lu @ 2026-06-15 6:50 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260615065003.76661-1-a0987203069@gmail.com>
The DC8200 and DCUltraLite share a broadly similar register layout but
differ in how the bridge, CRTC, primary plane and IRQ paths are driven.
Introduce a vs_dc_funcs vtable so each variant can supply its own
implementation without scattering conditionals across multiple files.
Add enum vs_dc_generation (VSDC_GEN_DC8000 / VSDC_GEN_DC8200) to
vs_hwdb.h and a generation field to struct vs_chip_identity. Annotate
all four existing DC8200 HWDB entries with VSDC_GEN_DC8200.
Extract the DC8200-specific hardware ops into a new vs_dc8200.c:
panel_enable_ex / panel_disable_ex - PANEL_CONFIG/START + CONFIG_EX commit
enable_vblank / disable_vblank - TOP_IRQ_EN VSYNC bit
primary_plane_enable_ex / disable_ex / update_ex - FB_CONFIG_EX path
irq_ack - reads TOP_IRQ_ACK
Update vs_bridge.c, vs_crtc.c, vs_primary_plane.c and vs_dc.c to
dispatch through dc->funcs instead of directly touching registers.
vs_crtc.c gains atomic_begin and atomic_flush hooks to allow variants
to gate per-frame commit cycles.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +---
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 ++++++-
drivers/gpu/drm/verisilicon/vs_dc.c | 6 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 32 ++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 4 +
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
9 files changed, 196 insertions(+), 51 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 426f4bcaa834..9d4cd16452fa 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_bridge.c b/drivers/gpu/drm/verisilicon/vs_bridge.c
index 7a93049368db..6ff2ac745b15 100644
--- a/drivers/gpu/drm/verisilicon/vs_bridge.c
+++ b/drivers/gpu/drm/verisilicon/vs_bridge.c
@@ -162,15 +162,8 @@ static void vs_bridge_enable_common(struct vs_crtc *crtc,
VSDC_DISP_PANEL_CONFIG_DE_EN |
VSDC_DISP_PANEL_CONFIG_DAT_EN |
VSDC_DISP_PANEL_CONFIG_CLK_EN);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_RUNNING(output));
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+
+ dc->funcs->panel_enable_ex(dc, output);
}
static void vs_bridge_atomic_enable_dpi(struct drm_bridge *bridge,
@@ -228,14 +221,7 @@ static void vs_bridge_atomic_disable(struct drm_bridge *bridge,
struct vs_dc *dc = crtc->dc;
unsigned int output = crtc->id;
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
- VSDC_DISP_PANEL_START_RUNNING(output));
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+ dc->funcs->panel_disable_ex(dc, output);
}
static const struct drm_bridge_funcs vs_dpi_bridge_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c
index 0b8a35d09cd2..679d6541ba1b 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc.c
+++ b/drivers/gpu/drm/verisilicon/vs_crtc.c
@@ -16,10 +16,33 @@
#include "vs_crtc_regs.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_plane.h"
+static void vs_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_begin)
+ dc->funcs->crtc_begin(dc, output);
+}
+
+static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_flush)
+ dc->funcs->crtc_flush(dc, output);
+
+ drm_crtc_vblank_atomic_flush(crtc, state);
+}
+
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_commit *state)
{
@@ -30,6 +53,9 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
clk_disable_unprepare(dc->pix_clk[output]);
+
+ if (dc->funcs->crtc_disable)
+ dc->funcs->crtc_disable(dc, output);
}
static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -42,6 +68,9 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
drm_WARN_ON(&dc->drm_dev->base,
clk_prepare_enable(dc->pix_clk[output]));
+ if (dc->funcs->crtc_enable)
+ dc->funcs->crtc_enable(dc, output);
+
drm_crtc_vblank_on(crtc);
}
@@ -119,7 +148,8 @@ static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
- .atomic_flush = drm_crtc_vblank_atomic_flush,
+ .atomic_begin = vs_crtc_atomic_begin,
+ .atomic_flush = vs_crtc_atomic_flush,
.atomic_enable = vs_crtc_atomic_enable,
.atomic_disable = vs_crtc_atomic_disable,
.mode_set_nofb = vs_crtc_mode_set_nofb,
@@ -132,7 +162,7 @@ static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->enable_vblank(dc, vcrtc->id);
return 0;
}
@@ -142,7 +172,7 @@ static void vs_crtc_disable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->disable_vblank(dc, vcrtc->id);
}
static const struct drm_crtc_funcs vs_crtc_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index dad9967bc10b..9729b693d360 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -8,9 +8,7 @@
#include <linux/of.h>
#include <linux/of_graph.h>
-#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_hwdb.h"
@@ -33,7 +31,7 @@ static irqreturn_t vs_dc_irq_handler(int irq, void *private)
struct vs_dc *dc = private;
u32 irqs;
- regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ irqs = dc->funcs->irq_ack(dc);
vs_drm_handle_irq(dc, irqs);
@@ -136,6 +134,8 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
+ dc->funcs = &vs_dc8200_funcs;
+
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
ret = -EINVAL;
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index ed1016f18758..544e1a37065b 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -14,6 +14,7 @@
#include <linux/reset.h>
#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
#include "vs_hwdb.h"
@@ -22,6 +23,34 @@
struct vs_drm_dev;
struct vs_crtc;
+struct vs_dc;
+
+struct vs_dc_funcs {
+ /* Bridge: atomic_enable, atomic_disable */
+ void (*panel_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*panel_disable_ex)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_begin, atomic_flush */
+ void (*crtc_begin)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_flush)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_enable, atomic_disable */
+ void (*crtc_enable)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_disable)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: enable_vblank, disable_vblank */
+ void (*enable_vblank)(struct vs_dc *dc, unsigned int output);
+ void (*disable_vblank)(struct vs_dc *dc, unsigned int output);
+
+ /* Primary plane: atomic_enable, atomic_disable, atomic_update */
+ void (*primary_plane_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*primary_plane_disable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*primary_plane_update_ex)(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state);
+
+ /* IRQ acknowledge */
+ u32 (*irq_ack)(struct vs_dc *dc);
+};
struct vs_dc {
struct regmap *regs;
@@ -33,6 +62,9 @@ struct vs_dc {
struct vs_drm_dev *drm_dev;
struct vs_chip_identity identity;
+ const struct vs_dc_funcs *funcs;
};
+extern const struct vs_dc_funcs vs_dc8200_funcs;
+
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
new file mode 100644
index 000000000000..800df9279e9b
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_bridge_regs.h"
+#include "vs_dc.h"
+#include "vs_dc_top_regs.h"
+#include "vs_plane.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8200_panel_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_panel_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_plane_commit(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_primary_plane_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+ regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
+ VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_primary_plane_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_primary_plane_update_ex(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state)
+{
+ regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
+ regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
+ state->crtc_y + state->crtc_h));
+ regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
+ VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static u32 vs_dc8200_irq_ack(struct vs_dc *dc)
+{
+ u32 irqs;
+
+ regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ return irqs;
+}
+
+const struct vs_dc_funcs vs_dc8200_funcs = {
+ .panel_enable_ex = vs_dc8200_panel_enable_ex,
+ .panel_disable_ex = vs_dc8200_panel_disable_ex,
+ .enable_vblank = vs_dc8200_enable_vblank,
+ .disable_vblank = vs_dc8200_disable_vblank,
+ .primary_plane_enable_ex = vs_dc8200_primary_plane_enable_ex,
+ .primary_plane_disable_ex = vs_dc8200_primary_plane_disable_ex,
+ .primary_plane_update_ex = vs_dc8200_primary_plane_update_ex,
+ .irq_ack = vs_dc8200_irq_ack,
+};
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 2a0f7c59afa3..91524d16f778 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -94,6 +94,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = ~0U,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -103,6 +104,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5721,
.customer_id = 0x30B,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -112,6 +114,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x310,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_with_yuv444,
@@ -121,6 +124,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x311,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.h b/drivers/gpu/drm/verisilicon/vs_hwdb.h
index 2065ecb73043..a15c8b565604 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.h
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.h
@@ -9,6 +9,11 @@
#include <linux/regmap.h>
#include <linux/types.h>
+enum vs_dc_generation {
+ VSDC_GEN_DC8000,
+ VSDC_GEN_DC8200,
+};
+
struct vs_formats {
const u32 *array;
unsigned int num;
@@ -19,6 +24,7 @@ struct vs_chip_identity {
u32 revision;
u32 customer_id;
+ enum vs_dc_generation generation;
u32 display_count;
/*
* The hardware only supports square cursor planes, so this field
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane.c b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
index 1f2be41ae496..f992cb277f61 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
@@ -53,12 +53,6 @@ static int vs_primary_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static void vs_primary_plane_commit(struct vs_dc *dc, unsigned int output)
-{
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_COMMIT);
-}
-
static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
struct drm_atomic_commit *atomic_state)
{
@@ -69,13 +63,8 @@ static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
- regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
- VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_enable_ex)
+ dc->funcs->primary_plane_enable_ex(dc, output);
}
static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
@@ -88,10 +77,8 @@ static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_disable_ex)
+ dc->funcs->primary_plane_disable_ex(dc, output);
}
static void vs_primary_plane_atomic_update(struct drm_plane *plane,
@@ -133,18 +120,11 @@ static void vs_primary_plane_atomic_update(struct drm_plane *plane,
regmap_write(dc->regs, VSDC_FB_STRIDE(output),
fb->pitches[0]);
- regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
- regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
- state->crtc_y + state->crtc_h));
regmap_write(dc->regs, VSDC_FB_SIZE(output),
VSDC_MAKE_PLANE_SIZE(state->crtc_w, state->crtc_h));
- regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
- VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->primary_plane_update_ex)
+ dc->funcs->primary_plane_update_ex(dc, output, state);
}
static const struct drm_plane_helper_funcs vs_primary_plane_helper_funcs = {
--
2.43.0
^ permalink raw reply related
* [PATCH v4 2/6] drm/verisilicon: add register-level macros for DC8000
From: Joey Lu @ 2026-06-15 6:49 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260615065003.76661-1-a0987203069@gmail.com>
Add register-level constants needed by the forthcoming DC8000 (DCUltraLite)
hardware ops:
VSDC_DISP_IRQ_VSYNC(n) in vs_crtc_regs.h: bit mask for per-output
VSYNC interrupt bits in DISP_IRQ_STA (0x147C) / DISP_IRQ_EN (0x1480),
which are the IRQ registers used by DCUltraLite in place of the DC8200
TOP_IRQ_ACK / TOP_IRQ_EN registers.
VSDC_FB_CONFIG_ENABLE (bit 0), VSDC_FB_CONFIG_VALID (bit 3) and
VSDC_FB_CONFIG_RESET (bit 4) in vs_primary_plane_regs.h: control bits
in the FB_CONFIG register used by DCUltraLite for framebuffer enable
and per-frame commit handshake.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
index c7930e817635..d4da22b08cd5 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
@@ -54,6 +54,7 @@
#define VSDC_DISP_GAMMA_DATA(n) (0x1460 + 0x4 * (n))
#define VSDC_DISP_IRQ_STA 0x147C
+#define VSDC_DISP_IRQ_VSYNC(n) BIT(n)
#define VSDC_DISP_IRQ_EN 0x1480
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
index cbb125c46b39..67d4b00f294e 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
@@ -16,6 +16,9 @@
#define VSDC_FB_STRIDE(n) (0x1408 + 0x4 * (n))
#define VSDC_FB_CONFIG(n) (0x1518 + 0x4 * (n))
+#define VSDC_FB_CONFIG_ENABLE BIT(0)
+#define VSDC_FB_CONFIG_VALID BIT(3)
+#define VSDC_FB_CONFIG_RESET BIT(4)
#define VSDC_FB_CONFIG_CLEAR_EN BIT(8)
#define VSDC_FB_CONFIG_ROT_MASK GENMASK(13, 11)
#define VSDC_FB_CONFIG_ROT(v) ((v) << 11)
--
2.43.0
^ permalink raw reply related
* [PATCH v4 1/6] dt-bindings: display: verisilicon,dc: generalize for single-output variants
From: Joey Lu @ 2026-06-15 6:49 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260615065003.76661-1-a0987203069@gmail.com>
The existing schema hard-codes the five-clock/three-reset/dual-port
topology of the DC8200 IP block, preventing reuse for single-output
variants such as the Verisilicon DCUltraLite used in the Nuvoton MA35D1
SoC.
Rework the schema so that variant-specific constraints are expressed via
allOf/if blocks:
- Add nuvoton,ma35d1-dcu to the SoC-specific compatible enum. The
generic verisilicon,dc fallback remains the driver-binding string.
- Move clock and reset items descriptions into the per-variant allOf/if
blocks; keep only minItems/maxItems at the top level so the base schema
accepts all variants.
- Restore full items lists for clock-names and reset-names at the top
level with minItems so the names are validated against the descriptions.
- Keep ports in the global required list and keep additionalProperties: false.
- Add an allOf/if block for thead,th1520-dc8200: five-clock (core, axi,
ahb, pix0, pix1), three-reset (core, axi, ahb), required resets.
- Add an allOf/if block for nuvoton,ma35d1-dcu: two-clock (core, pix0),
one-reset (core), required resets.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
.../bindings/display/verisilicon,dc.yaml | 80 +++++++++++++++++--
1 file changed, 73 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
index 9dc35ab973f2..0c41286b8223 100644
--- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
+++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
@@ -17,6 +17,7 @@ properties:
items:
- enum:
- thead,th1520-dc8200
+ - nuvoton,ma35d1-dcu
- const: verisilicon,dc # DC IPs have discoverable ID/revision registers
reg:
@@ -26,14 +27,12 @@ properties:
maxItems: 1
clocks:
- items:
- - description: DC Core clock
- - description: DMA AXI bus clock
- - description: Configuration AHB bus clock
- - description: Pixel clock of output 0
- - description: Pixel clock of output 1
+ minItems: 2
+ maxItems: 5
clock-names:
+ minItems: 2
+ maxItems: 5
items:
- const: core
- const: axi
@@ -42,12 +41,16 @@ properties:
- const: pix1
resets:
+ minItems: 1
+ maxItems: 3
items:
- description: DC Core reset
- description: DMA AXI bus reset
- description: Configuration AHB bus reset
reset-names:
+ minItems: 1
+ maxItems: 3
items:
- const: core
- const: axi
@@ -59,7 +62,7 @@ properties:
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
- description: The first output channel , endpoint 0 should be
+ description: The first output channel, endpoint 0 should be
used for DPI format output and endpoint 1 should be used
for DP format output.
@@ -77,6 +80,69 @@ required:
- clock-names
- ports
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: thead,th1520-dc8200
+ then:
+ properties:
+ clocks:
+ minItems: 5
+ maxItems: 5
+ items:
+ - description: DC Core clock
+ - description: DMA AXI bus clock
+ - description: Configuration AHB bus clock
+ - description: Pixel clock of output 0
+ - description: Pixel clock of output 1
+
+ clock-names:
+ minItems: 5
+ maxItems: 5
+
+ resets:
+ minItems: 3
+ maxItems: 3
+
+ reset-names:
+ minItems: 3
+ maxItems: 3
+
+ required:
+ - resets
+ - reset-names
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nuvoton,ma35d1-dcu
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 2
+ items:
+ - description: DC Core clock
+ - description: Pixel clock of output 0
+
+ clock-names:
+ minItems: 2
+ maxItems: 2
+
+ resets:
+ minItems: 1
+ maxItems: 1
+
+ reset-names:
+ maxItems: 1
+
+ required:
+ - resets
+ - reset-names
+
additionalProperties: false
examples:
--
2.43.0
^ permalink raw reply related
* [PATCH v4 0/6] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
From: Joey Lu @ 2026-06-15 6:49 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
This series adds support for the Verisilicon DCUltraLite display
controller as integrated in the Nuvoton MA35D1 SoC.
The Verisilicon DC driver and its DT binding were originally written by
Icenowy Zheng <zhengxingda@iscas.ac.cn> for the T-Head TH1520 SoC, which
carries a DC8200 IP block. The present series builds on that foundation
with gratitude to Icenowy for the original work.
The DCUltraLite is a different variant in the DC IP family. While the two
IPs share a broadly similar register layout, a number of differences
prevent the existing driver from working on the MA35D1 without
modification:
- No CONFIG_EX commit path: the DC8200 staging registers
(FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT, FB_BLEND_CONFIG,
PANEL_CONFIG_EX) are absent. The DCUltraLite uses enable (bit 0) and
reset (bit 4) bits in FB_CONFIG for direct framebuffer updates, and
requires a per-frame VALID bit toggle (FB_CONFIG bit 3) to latch
configuration changes.
- No PANEL_START register: panel output begins when
PANEL_CONFIG.RUNNING is set; the DC8200 multi-display sync start
register at 0x1CCC does not exist.
- Different IRQ registers: DISP_IRQ_STA at 0x147C / DISP_IRQ_EN at
0x1480, versus the DC8200's TOP_IRQ_ACK at 0x0010 / TOP_IRQ_EN at
0x0014.
- Simpler clock topology: two clocks ("core" bus gate and "pix0" pixel
divider); no axi or ahb clocks required.
- Single display output: no per-output indexing beyond index 0 is
needed.
- Hardware-discoverable identity: the DCUltraLite exposes chip identity
registers whose model field reads 0x0 (revision 0x5560,
customer_id 0x305), allowing the existing vs_fill_chip_identity()
path to identify the variant purely through register reads.
Patch 1 generalises the verisilicon,dc DT binding to accommodate the
Nuvoton MA35D1 SoC-specific compatible and the variant's two-clock,
one-reset, single-port topology.
Patch 2 adds the register-level macros needed by the DC8000 ops.
Patches 3-5 introduce the driver changes in three logical steps: the
vs_dc_funcs hardware ops vtable with DC8200 ops extracted into
vs_dc8200.c; the DC8000 ops in vs_dc8000.c with the necessary
clock-optionality changes; and finally the DCUltraLite HWDB entry that
gates hardware recognition once all support is in place.
Patch 6 adds the Kconfig dependency on ARCH_MA35, placed last because it
is only meaningful after the HWDB entry is added.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v3:
- [dt-bindings] Reverted extra space before inline '#' comment.
- [dt-bindings] Moved clock/reset items descriptions from the top-level
clocks:/resets: into the per-variant allOf/if blocks; kept only
minItems/maxItems at the top level.
- [dt-bindings] Restored full items lists for clock-names and reset-names
at the top level with minItems so names are still validated.
- [dt-bindings] Added minItems: 1 to resets: in the nuvoton block.
- [dt-bindings] Added required: [resets, reset-names] inside the then:
block for both thead,th1520-dc8200 and nuvoton,ma35d1-dcu.
- [dt-bindings] Added minItems: 3 to reset-names in the thead block.
- [dt-bindings] Added maxItems: 1 to reset-names in the nuvoton block.
- [dt-bindings] Reverted unevaluatedProperties: false back to
additionalProperties: false.
- [dt-bindings] Removed the second DT example for nuvoton,ma35d1-dcu
since a difference in clocks/resets does not need a new example.
- [ops] Renamed bridge_enable/bridge_disable to panel_enable_ex/
panel_disable_ex.
- [ops] Renamed irq_handler to irq_ack.
- [ops] Renamed plane_enable_ex/disable_ex/update_ex to
primary_plane_enable_ex/disable_ex/update_ex.
- [ops] Renamed vs_dcu_lite.c to vs_dc8000.c, all internal functions
from vs_dcu_lite_* to vs_dc8000_*, exported symbol from
vs_dcu_lite_funcs to vs_dc8000_funcs; updated Makefile.
- [kconfig] Moved ARCH_MA35 Kconfig change to a separate final commit,
placed after the HWDB entry.
Joey Lu (6):
dt-bindings: display: verisilicon,dc: generalize for single-output
variants
drm/verisilicon: add register-level macros for DC8000
drm/verisilicon: introduce per-variant hardware ops table
drm/verisilicon: add DC8000 (DCUltraLite) display controller support
drm/verisilicon: add DCUltraLite chip identity to HWDB
drm/verisilicon: extend Kconfig to support ARCH_MA35 platforms
.../bindings/display/verisilicon,dc.yaml | 80 +++++++++++--
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +---
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 ++++++-
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc.c | 13 ++-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 ++++++
drivers/gpu/drm/verisilicon/vs_dc8000.c | 78 +++++++++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 14 +++
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
.../drm/verisilicon/vs_primary_plane_regs.h | 3 +
14 files changed, 368 insertions(+), 61 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8000.c
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
--
2.43.0
^ permalink raw reply
* Re: [PATCH] dt-bindings: sound: nvidia,tegra30-ahub: Convert to DT schema
From: Krzysztof Kozlowski @ 2026-06-15 6:50 UTC (permalink / raw)
To: Charan Pedumuru
Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, linux-sound,
devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260613-nvidia-ahub-v1-1-5b7e85301736@gmail.com>
On Sat, Jun 13, 2026 at 08:24:47AM +0000, Charan Pedumuru wrote:
> Convert NVIDIA Tegra Audio Hub (AHUB) binding to DT schema.
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
ASoC: dt-bindings:
...
> +description:
> + The NVIDIA Tegra AHUB (Audio Hub) is an audio interconnect block used to
> + route data between various audio clients such as I2S, DAM, SPDIF, and
> + APBIF. It exposes multiple register regions and supports different
> + configurations depending on the Tegra SoC generation. The AHUB also
> + provides a configlink bus for child audio components, which use CIF
> + (Client Interface) IDs to identify their data paths. The number of DMA
> + channels, reset lines, and additional modules varies across Tegra30,
> + Tegra114, and Tegra124 platforms.
> +
> +properties:
> + compatible:
> + oneOf:
> + - const: nvidia,tegra30-ahub
> + - const: nvidia,tegra114-ahub
> + - const: nvidia,tegra124-ahub
These three are enum and please sort alphanumerically, not by natural
sorting (so 30 > 124)
> + - items:
> + - const: nvidia,tegra132-ahub
> + - const: nvidia,tegra124-ahub
> +
> + reg:
> + minItems: 2
> + maxItems: 3
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: Clock for the D_AUDIO domain
> + - description: Clock for the APBIF interface
> +
> + clock-names:
> + items:
> + - const: d_audio
> + - const: apbif
> +
> + resets:
> + minItems: 11
> + maxItems: 21
> +
> + reset-names:
> + oneOf:
> + # Tegra30: d_audio apbif i2s0-4 dam0-2 spdif
> + - items:
> + - const: d_audio
> + - const: apbif
> + - const: i2s0
> + - const: i2s1
> + - const: i2s2
> + - const: i2s3
> + - const: i2s4
> + - const: dam0
> + - const: dam1
> + - const: dam2
> + - const: spdif
> +
> + # Tegra114: adds amx adx
> + - items:
> + - const: d_audio
> + - const: apbif
> + - const: i2s0
> + - const: i2s1
> + - const: i2s2
> + - const: i2s3
> + - const: i2s4
> + - const: dam0
> + - const: dam1
> + - const: dam2
> + - const: spdif
> + - const: amx
> + - const: adx
> +
> + # Tegra124: adds amx1 adx1 afc0-5
> + - items:
> + - const: d_audio
> + - const: apbif
> + - const: i2s0
> + - const: i2s1
> + - const: i2s2
> + - const: i2s3
> + - const: i2s4
> + - const: dam0
> + - const: dam1
> + - const: dam2
> + - const: spdif
> + - const: amx
> + - const: amx1
> + - const: adx
> + - const: adx1
> + - const: afc0
> + - const: afc1
> + - const: afc2
> + - const: afc3
> + - const: afc4
> + - const: afc5
These should be placed in allOf: section. Here define only min/maxItems.
> +
> + dmas:
> + minItems: 8
> + maxItems: 20
> +
> + dma-names:
> + oneOf:
> + # Tegra30: rx0..rx3 tx0..tx3 (n=3)
> + - items:
> + - const: rx0
> + - const: tx0
> + - const: rx1
> + - const: tx1
> + - const: rx2
> + - const: tx2
> + - const: rx3
> + - const: tx3
> +
> + # Tegra114/124: rx0..rx9 tx0..tx9 (n=9)
> + - items:
> + - const: rx0
> + - const: tx0
> + - const: rx1
> + - const: tx1
> + - const: rx2
> + - const: tx2
> + - const: rx3
> + - const: tx3
> + - const: rx4
> + - const: tx4
> + - const: rx5
> + - const: tx5
> + - const: rx6
> + - const: tx6
> + - const: rx7
> + - const: tx7
> + - const: rx8
> + - const: tx8
> + - const: rx9
> + - const: tx9
Keep this list (so drop the "oneOf") and add minItems. Then in
allOf:if:then: block you customize min/maxItems.
> +
> + "#address-cells":
> + $ref: /schemas/types.yaml#/definitions/uint32
> +
> + "#size-cells":
> + $ref: /schemas/types.yaml#/definitions/uint32
You do not need types. You need values (const). See also other bindings
for examples. Even if this is MMIO bus, I doubt children need 64-bit
addressing, so this should be really 32-bit (thus const:1 , not even
enum). If you need 64-bit addressing (e.g. for DMA), this would have to
be explained.
> +
> + ranges: true
> +
> +patternProperties:
> + "^i2s@[0-9a-f]+$":
I think this was not in the old binding. so you need to explain in
commit msg why you made this change to the binding.
> + type: object
> +
> + allOf:
> + - $ref: /schemas/sound/nvidia,tegra30-i2s.yaml#
$ref directly, no need for allOf
> +
> + properties:
> + nvidia,ahub-cif-ids:
> + description: Pair of AHUB CIF IDs for the RX and TX data paths.
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + minItems: 2
> + maxItems: 2
> +
> + required:
> + - nvidia,ahub-cif-ids
Why do you need the properties and required here? The child (i2s) schema
should define that.
> +
> + unevaluatedProperties: false
> +
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v4 5/7] arm64: dts: renesas: r8a779g0: Add DSC
From: sashiko-bot @ 2026-06-15 6:43 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: devicetree, robh, wsa+renesas, dri-devel, conor+dt
In-Reply-To: <20260615-rcar-du-dsc-v4-5-93096a1b56a3@ideasonboard.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] `WARN_ON(pm_runtime_get_sync())` triggers a spurious warning and leaks the usage counter on failure.
--
commit 0b204c1dc5dc2b356c39f6b89ab2b1606d6ffb6b
Author: Marek Vasut <marek.vasut+renesas@mailbox.org>
arm64: dts: renesas: r8a779g0: Add DSC
The Renesas DSC Display Stream Compression is a bridge embedded in the
Renesas R-Car V4H SoC. The current dtsi file does not represent the DSC at
all, and thus the pipeline for DSI1 has not been functional.
> diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
> index 82a7278836e57..123baaea8db45 100644
> --- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
> @@ -2298,6 +2298,35 @@ du_out_dsi0: endpoint {
[ ... ]
> + dsc: bridge@feb8d000 {
> + compatible = "renesas,r8a779g0-dsc", "renesas,rcar-dsc";
[Severity: High]
This isn't a bug introduced by this patch, but enabling this device node
activates preexisting code in the driver added earlier in the series which
has an issue in the runtime PM error path.
Looking at rcar_dsc_atomic_enable() in drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c:
drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c:rcar_dsc_atomic_enable() {
struct rcar_dsc *dsc = bridge_to_rcar_dsc(bridge);
WARN_ON(pm_runtime_get_sync(dsc->dev));
}
Since pm_runtime_get_sync() returns 1 if the device is already in the
RPM_ACTIVE state, will evaluating WARN_ON(pm_runtime_get_sync(dsc->dev))
trigger a spurious kernel warning stack trace on every atomic enable if the
device is already active or if runtime PM is disabled?
Furthermore, if pm_runtime_get_sync() fails (returns < 0), the PM
usage counter is still incremented by the subsystem. Since the error path does
not call pm_runtime_put_noidle(), does this leak the PM usage counter and
prevent the device from ever suspending?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615-rcar-du-dsc-v4-0-93096a1b56a3@ideasonboard.com?part=5
^ permalink raw reply
* Re: [PATCH v4 6/7] arm64: dts: renesas: sparrow-hawk: Enable DisplayPort by adding DSC
From: sashiko-bot @ 2026-06-15 6:43 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: wsa+renesas, conor+dt, dri-devel, robh, devicetree
In-Reply-To: <20260615-rcar-du-dsc-v4-6-93096a1b56a3@ideasonboard.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Incorrect PM Runtime error handling and improper use of `WARN_ON`.
- [High] DRM bridge registration occurs before PM runtime is enabled.
- [High] Blind dereference of an unvalidated bridge pointer when skipping the DSC block.
- [High] Hardcoding the DSC bridge in the SoC `.dtsi` breaks the display for boards that disable the DSC.
- [Low] Call to a non-existent function `of_drm_get_bridge_by_endpoint`.
--
commit 9f241229b3364b6a9d83e1e7ed9e9076efdd0876
Author: Marek Vasut <marek.vasut+renesas@mailbox.org>
arm64: dts: renesas: sparrow-hawk: Enable DisplayPort by adding DSC
This commit enables the DisplayPort output on the sparrowhawk board by
activating the newly defined DSC block in the SoC device tree. It completes
the DSC series by wiring up the components for this specific board.
> diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
> index 82a7278836e57..123baaea8db45 100644
> --- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
> @@ -2298,6 +2298,35 @@ du_out_dsi0: endpoint {
> port@1 {
> reg = <1>;
> du_out_dsi1: endpoint {
> + remote-endpoint = <&dsc_in_dsi1>;
[Severity: High]
Will hardcoding the remote-endpoint to the DSC bridge break the display for
boards that disable the DSC?
Because the DSC node is marked status = "disabled" by default below, the DRM
OF helpers will return -ENODEV when the DU driver traverses this graph. This
would cause the DU probe to return -EPROBE_DEFER or -ENODEV indefinitely,
breaking the display pipeline for all boards based on this SoC that do not
explicitly enable the DSC.
> + };
> + };
> + };
> + };
> +
> + dsc: bridge@feb8d000 {
[ ... ]
> diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c b/drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c
> new file mode 100644
> index 0000000000000..5a2ff31491360
> --- /dev/null
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c
[ ... ]
> +static void rcar_dsc_atomic_enable(struct drm_bridge *bridge,
> + struct drm_atomic_commit *commit)
> +{
> + struct rcar_dsc *dsc = bridge_to_rcar_dsc(bridge);
> +
> + WARN_ON(pm_runtime_get_sync(dsc->dev));
[Severity: High]
Is it safe to wrap pm_runtime_get_sync() directly in a WARN_ON()?
If the device is already active, pm_runtime_get_sync() returns 1, which will
falsely trigger a warning and stack trace here on valid hot paths. If the
function returns a negative error code, the warning is printed but the
PM usage counter is not decremented, leaking the PM reference and attempting
to configure an unpowered device.
> +}
[ ... ]
> +static int rcar_dsc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct rcar_dsc *dsc;
> + int ret;
> +
> + dsc = devm_drm_bridge_alloc(dev, struct rcar_dsc, bridge,
> + &rcar_dsc_bridge_ops);
> + if (IS_ERR(dsc))
> + return PTR_ERR(dsc);
> +
> + platform_set_drvdata(pdev, dsc);
> +
> + dsc->dev = &pdev->dev;
> +
> + dsc->bridge.next_bridge = of_drm_get_bridge_by_endpoint(dev->of_node,
> + 1, 0);
[Severity: Low]
Could you clarify if the function of_drm_get_bridge_by_endpoint() exists in
the kernel tree?
It appears the correct API might be devm_drm_of_get_bridge() or
drm_of_find_panel_or_bridge(). Using a non-existent function will cause an
immediate build failure due to -Werror=implicit-function-declaration.
> + if (IS_ERR(dsc->bridge.next_bridge))
> + return PTR_ERR(dsc->bridge.next_bridge);
> +
> + dsc->bridge.of_node = dev->of_node;
> +
> + ret = devm_drm_bridge_add(dev, &dsc->bridge);
> + if (ret)
> + return ret;
> +
> + pm_runtime_enable(&pdev->dev);
[Severity: High]
Can registering the DRM bridge before enabling PM runtime introduce a race
condition?
Calling devm_drm_bridge_add() exposes the bridge globally to other drivers
like the DU driver while its PM runtime is still disabled. If another driver
attaches and enables the bridge during this window, pm_runtime_get_sync() will
fail with -EACCES.
> +
> + return 0;
> +}
[ ... ]
> diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
> index 1a246ebbfc613..5679983fc4d1a 100644
> --- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
> @@ -754,6 +754,15 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
> (BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) {
> struct drm_bridge *bridge = rcdu->dsi[rcrtc->index];
>
> + /*
> + * When we have a DSC block between the DU and the DSI,
> + * the "bridge" points to the DSC. Detect the DSC by looking
> + * at the bridge type, and skip the DSC if the bridge is not
> + * the DSI bridge.
> + */
> + if (bridge->type != DRM_MODE_CONNECTOR_DSI)
> + bridge = bridge->next_bridge;
> +
> rcar_mipi_dsi_pclk_enable(bridge, state);
[Severity: High]
What prevents a blind dereference of bridge->next_bridge from causing an
invalid pointer computation here?
If next_bridge is NULL (e.g., due to a disconnected or missing OF graph node)
or is not a MIPI DSI bridge, passing it into rcar_mipi_dsi_pclk_enable() will
cause bridge_to_rcar_mipi_dsi() to compute an invalid pointer via
container_of. This regression could result in memory corruption or an
immediate system crash.
> }
>
> @@ -796,6 +805,15 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
> (BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) {
> struct drm_bridge *bridge = rcdu->dsi[rcrtc->index];
>
> + /*
> + * When we have a DSC block between the DU and the DSI,
> + * the "bridge" points to the DSC. Detect the DSC by looking
> + * at the bridge type, and skip the DSC if the bridge is not
> + * the DSI bridge.
> + */
> + if (bridge->type != DRM_MODE_CONNECTOR_DSI)
> + bridge = bridge->next_bridge;
> +
> /*
> * Disable the DSI clock output, see
> * rcar_du_crtc_atomic_enable().
[Severity: High]
Similarly to the enable path, is this unchecked dereference of
bridge->next_bridge safe in the disable path?
If next_bridge is NULL or not a MIPI DSI bridge, it will be passed to
rcar_mipi_dsi_pclk_disable() where bridge_to_rcar_mipi_dsi() will compute an
invalid pointer, leading to a similar regression where memory is corrupted.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615-rcar-du-dsc-v4-0-93096a1b56a3@ideasonboard.com?part=6
^ permalink raw reply
* Re: [PATCH v4 4/7] drm/rcar-du: dsi: Support DSC in the pipeline
From: sashiko-bot @ 2026-06-15 6:40 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: dri-devel, wsa+renesas, conor+dt, robh, devicetree
In-Reply-To: <20260615-rcar-du-dsc-v4-4-93096a1b56a3@ideasonboard.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unsafe bridge advancement leads to NULL pointer dereference and type confusion
--
commit 1b871953b11e075ad828c5d792325efbdffe6d91
Author: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
drm/rcar-du: dsi: Support DSC in the pipeline
This commit adds checks to rcar_du_crtc_atomic_enable() and disable() to
detect the DSC via the bridge type. It skips the DSC bridge when needed so
that the crtc correctly calls rcar_mipi_dsi_pclk_enable() on the DSI instead
of the DSC.
> diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
> index 1a246ebbfc613..5679983fc4d1a 100644
> --- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_crtc.c
> @@ -754,6 +754,15 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
[ ... ]
> if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) &&
> (rstate->outputs &
> (BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) {
> struct drm_bridge *bridge = rcdu->dsi[rcrtc->index];
>
> + /*
> + * When we have a DSC block between the DU and the DSI,
> + * the "bridge" points to the DSC. Detect the DSC by looking
> + * at the bridge type, and skip the DSC if the bridge is not
> + * the DSI bridge.
> + */
> + if (bridge->type != DRM_MODE_CONNECTOR_DSI)
> + bridge = bridge->next_bridge;
> +
[Severity: High]
Could this lead to a NULL pointer dereference or type confusion if the device
tree is misconfigured?
If bridge->next_bridge is NULL, passing it to rcar_mipi_dsi_pclk_enable()
would dereference a NULL pointer when it accesses bridge->encoder.
Additionally, if the next bridge exists but is not an rcar_mipi_dsi bridge
(for instance, a generic panel bridge), the container_of() cast in
bridge_to_rcar_mipi_dsi() would result in type confusion and potential
memory corruption.
Should we verify that the new bridge is valid and is actually the expected DSI
bridge before proceeding?
> rcar_mipi_dsi_pclk_enable(bridge, state);
> }
>
> @@ -796,6 +805,15 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
[ ... ]
> if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) &&
> (rstate->outputs &
> (BIT(RCAR_DU_OUTPUT_DSI0) | BIT(RCAR_DU_OUTPUT_DSI1)))) {
> struct drm_bridge *bridge = rcdu->dsi[rcrtc->index];
>
> + /*
> + * When we have a DSC block between the DU and the DSI,
> + * the "bridge" points to the DSC. Detect the DSC by looking
> + * at the bridge type, and skip the DSC if the bridge is not
> + * the DSI bridge.
> + */
> + if (bridge->type != DRM_MODE_CONNECTOR_DSI)
> + bridge = bridge->next_bridge;
> +
[Severity: High]
Would this have the same risk of a NULL pointer dereference or type confusion
during the disable path when passed to rcar_mipi_dsi_pclk_disable()?
> /*
> * Disable the DSI clock output, see
> * rcar_du_crtc_atomic_enable().
> */
> rcar_mipi_dsi_pclk_disable(bridge);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615-rcar-du-dsc-v4-0-93096a1b56a3@ideasonboard.com?part=4
^ permalink raw reply
* Re: [PATCH v4 3/7] drm/rcar-du: dsc: Add rudimentary Renesas R-Car V4H DSC driver
From: sashiko-bot @ 2026-06-15 6:40 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: robh, wsa+renesas, conor+dt, devicetree, dri-devel
In-Reply-To: <20260615-rcar-du-dsc-v4-3-93096a1b56a3@ideasonboard.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] `WARN_ON(pm_runtime_get_sync(dsc->dev))` incorrectly warns on success and mishandles errors.
- [High] Mixing devm-managed bridge registration with manual runtime PM manipulation creates race conditions during probe and removal.
- [Low] The driver calls `of_drm_get_bridge_by_endpoint()`, which does not exist anywhere in the kernel, causing a build failure.
- [Low] Dead Kconfig dependency prevents `DRM_RCAR_DSC` from ever compiling under `COMPILE_TEST`.
--
commit 6b399ab87555498e65f4bb3171342804aa8feb3a
Author: Marek Vasut <marek.vasut+renesas@mailbox.org>
drm/rcar-du: dsc: Add rudimentary Renesas R-Car V4H DSC driver
The Renesas DSC Display Stream Compression is a bridge embedded in the
Renesas R-Car V4H SoC. The bridge performs VESA DSC encoding of up to
8k or 400 Mpixel/s. Add rudimentary driver, which currently acts as a
pass-through bridge and allows DSI1 to be operational on R-Car V4H.
> diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig
> index 840305fdeb49a..80bd770ae0f68 100644
> --- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
[ ... ]
> @@ -25,6 +25,18 @@ config DRM_RCAR_CMM
> def_tristate DRM_RCAR_DU
> depends on DRM_RCAR_USE_CMM
>
> +config DRM_RCAR_USE_DSC
> + bool "R-Car DU DSC Encoder Support"
> + depends on DRM_BRIDGE && OF
> + depends on DRM_RCAR_DU || COMPILE_TEST
> + default DRM_RCAR_DU
> + help
> + Enable support for the R-Car Display Unit embedded DSC encoder.
> +
> +config DRM_RCAR_DSC
> + def_tristate DRM_RCAR_DU
> + depends on DRM_RCAR_USE_DSC
> +
[Severity: Low]
Will this Kconfig setup prevent compile testing?
Since DRM_RCAR_USE_DSC depends on DRM_RCAR_DU || COMPILE_TEST, it can be
enabled when DRM_RCAR_DU=n. However, DRM_RCAR_DSC defaults to
def_tristate DRM_RCAR_DU.
This means when DRM_RCAR_DU=n during a COMPILE_TEST, DRM_RCAR_DSC will be
forced to 'n' and rcar_dsc.c will never actually be compiled.
> diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c b/drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c
> new file mode 100644
> index 0000000000000..5a2ff31491360
> --- /dev/null
> +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_dsc.c
[ ... ]
> +static void rcar_dsc_atomic_enable(struct drm_bridge *bridge,
> + struct drm_atomic_commit *commit)
> +{
> + struct rcar_dsc *dsc = bridge_to_rcar_dsc(bridge);
> +
> + WARN_ON(pm_runtime_get_sync(dsc->dev));
> +}
[Severity: High]
Does this WARN_ON trigger on success?
pm_runtime_get_sync() returns 1 when the device is already active
(RPM_ACTIVE). By wrapping it directly in WARN_ON(), wouldn't this trigger
a false-positive stack trace on every successful modeset?
[ ... ]
> +static int rcar_dsc_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct rcar_dsc *dsc;
> + int ret;
[ ... ]
> + dsc->bridge.next_bridge = of_drm_get_bridge_by_endpoint(dev->of_node,
> + 1, 0);
[Severity: Low]
Does this function exist?
Calling of_drm_get_bridge_by_endpoint() causes a build failure because it
doesn't exist anywhere in the kernel. Was this intended to be
devm_drm_of_get_bridge()?
> + if (IS_ERR(dsc->bridge.next_bridge))
> + return PTR_ERR(dsc->bridge.next_bridge);
> +
> + dsc->bridge.of_node = dev->of_node;
> +
> + ret = devm_drm_bridge_add(dev, &dsc->bridge);
> + if (ret)
> + return ret;
> +
> + pm_runtime_enable(&pdev->dev);
> +
> + return 0;
> +}
> +
> +static void rcar_dsc_remove(struct platform_device *pdev)
> +{
> + pm_runtime_disable(&pdev->dev);
> +}
[Severity: High]
Can these devres and manual pm_runtime calls race?
In rcar_dsc_probe(), devm_drm_bridge_add() exposes the bridge to the DRM
subsystem before pm_runtime_enable() is called.
On teardown, rcar_dsc_remove() manually calls pm_runtime_disable(), but the
devres-managed bridge isn't removed until devres_release_all() runs later.
Doesn't this create a window where the bridge is fully accessible via DRM
but its PM runtime is disabled, potentially causing hardware access faults
during concurrent operations?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260615-rcar-du-dsc-v4-0-93096a1b56a3@ideasonboard.com?part=3
^ permalink raw reply
* Re: [PATCH v4 2/7] dt-bindings: display: bridge: Document Renesas R-Car V4H DSC bindings
From: Tomi Valkeinen @ 2026-06-15 6:39 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: linux-renesas-soc, linux-clk, linux-kernel, dri-devel, devicetree,
Geert Uytterhoeven, Michael Turquette, Stephen Boyd,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Magnus Damm, Marek Vasut,
Laurent Pinchart, Kieran Bingham, Philipp Zabel, Conor Dooley
In-Reply-To: <20260615-rcar-du-dsc-v4-2-93096a1b56a3@ideasonboard.com>
Hi,
On 15/06/2026 09:28, Tomi Valkeinen wrote:
> From: Marek Vasut <marek.vasut+renesas@mailbox.org>
>
> The Renesas DSC Display Stream Compression is a bridge embedded in the
> Renesas R-Car V4H SoC. The bridge performs VESA DSC encoding of up to
> 8k or 400 Mpixel/s .
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> [tomi.valkeinen: fix the example]
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> ---
> .../bindings/display/bridge/renesas,dsc.yaml | 99 ++++++++++++++++++++++
> 1 file changed, 99 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dsc.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,dsc.yaml
> new file mode 100644
> index 000000000000..4d2c2c6cb1f0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dsc.yaml
> @@ -0,0 +1,99 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/renesas,dsc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Renesas R-Car DSC Display Stream Compression
> +
> +maintainers:
> + - Marek Vasut <marek.vasut+renesas@mailbox.org>
> +
> +description: |
> + This binding describes the VESA DSC Display Stream Compression encoder
> + embedded in the Renesas R-Car V4H SoC. The encoder supports all DSC1.1
> + encoding mechanisms, configurable bits-per-pixel, resolution up to 8k.
> +
> +properties:
> + compatible:
> + items:
> + - enum:
> + - renesas,r8a779g0-dsc
> + - const: renesas,rcar-dsc
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + power-domains:
> + maxItems: 1
> +
> + resets:
> + maxItems: 1
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> +
> + properties:
> + port@0:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: R-Car DU input port
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: R-Car DSI output port
> +
> + required:
> + - port@0
> + - port@1
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - interrupts
> + - power-domains
> + - resets
> + - ports
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/r8a779g0-cpg-mssr.h>
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/power/r8a779g0-sysc.h>
> +
> + bridge@feb8d000 {
> + compatible = "renesas,r8a779g0-dsc";
I missed adding "renesas,rcar-dsc" here.
Tomi
^ 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