* [PATCH v6 2/3] arm64: dts: freescale: Add support for Variscite VAR-SOM-MX8 QuadMax
From: Stefano Radaelli @ 2026-07-17 10:29 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Daniel Baluta, Josua Mayer,
Alexander Stein, Ernest Van Hoecke, Maud Spierings,
Francesco Dolcini, Hugo Villeneuve
In-Reply-To: <cover.1784284092.git.stefano.r@variscite.com>
From: Stefano Radaelli <stefano.r@variscite.com>
Add device tree support for the Variscite VAR-SOM-MX8 QuadMax
system on module.
This SOM is designed to be used with various carrier boards.
The module includes:
- NXP i.MX8 QuadMax MPU processor
- Up to 8GB of LPDDR4 memory
- Up to 128GB of eMMC storage memory
- Integrated 10/100/1000 Mbps Ethernet Transceiver
- Codec audio WM8904
- WIFI6 dual-band 802.11ax/ac/a/b/g/n with optional 802.15.4 and Bluetooth
Only SOM-specific peripherals are enabled by default. Carrier board
specific interfaces are left disabled to be enabled in the respective
carrier board device trees.
Link: https://variscite.com/system-on-module-som/i-mx-8/i-mx-8-quadmax-quadplus/var-som-mx8/
Signed-off-by: Stefano Radaelli <stefano.r@variscite.com>
---
v5->v6:
- Fix regulator typo
v4->v5:
- Fix sai7 clock
- Fix codec regulator voltage
v3->v4:
- Fix sai peripherals clocks
- Add comment to clarify 1GB variant
v2->v3:
-
v1->v2:
- Added non-removable property to usdhc3
- Removed unused fec gpio pinctrl
.../boot/dts/freescale/imx8qm-var-som.dtsi | 531 ++++++++++++++++++
1 file changed, 531 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi
new file mode 100644
index 000000000000..b11da10c5ae3
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Common dtsi for Variscite VAR-SOM-MX8
+ *
+ * Link: https://variscite.com/system-on-module-som/i-mx-8/i-mx-8-quadmax-quadplus/var-som-mx8/
+ *
+ * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/
+ *
+ */
+
+/dts-v1/;
+
+#include "imx8qm.dtsi"
+
+/ {
+ model = "Variscite i.MX8QM VAR-SOM-MX8 Module";
+ compatible = "variscite,var-som-imx8qm", "fsl,imx8qm";
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000 0 0x40000000>;
+ };
+
+ reg_audio_supply: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "wm8904-supply";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_phy_vddio: regulator-phy-vddio {
+ compatible = "regulator-fixed";
+ regulator-name = "vddio-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ vdev0vring0: memory@90000000 {
+ reg = <0 0x90000000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: memory@90008000 {
+ reg = <0 0x90008000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: memory@90010000 {
+ reg = <0 0x90010000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: memory@90018000 {
+ reg = <0 0x90018000 0 0x8000>;
+ no-map;
+ };
+
+ rsc_table0: memory@900ff000 {
+ reg = <0 0x900ff000 0 0x1000>;
+ no-map;
+ };
+
+ vdev2vring0: memory@90100000 {
+ reg = <0 0x90100000 0 0x8000>;
+ no-map;
+ };
+
+ vdev2vring1: memory@90108000 {
+ reg = <0 0x90108000 0 0x8000>;
+ no-map;
+ };
+
+ vdev3vring0: memory@90110000 {
+ reg = <0 0x90110000 0 0x8000>;
+ no-map;
+ };
+
+ vdev3vring1: memory@90118000 {
+ reg = <0 0x90118000 0 0x8000>;
+ no-map;
+ };
+
+ rsc_table1: memory@901ff000 {
+ reg = <0 0x901ff000 0 0x1000>;
+ no-map;
+ };
+
+ vdevbuffer: memory@90400000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x90400000 0 0x100000>;
+ no-map;
+ };
+
+ dsp_reserved: memory@92400000 {
+ reg = <0 0x92400000 0 0x1000000>;
+ no-map;
+ };
+
+ dsp_vdev0vring0: memory@942f0000 {
+ reg = <0 0x942f0000 0 0x8000>;
+ no-map;
+ };
+
+ dsp_vdev0vring1: memory@942f8000 {
+ reg = <0 0x942f8000 0 0x8000>;
+ no-map;
+ };
+
+ dsp_vdev0buffer: memory@94300000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x94300000 0 0x100000>;
+ no-map;
+ };
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ /* VAR-SOM-MX8QM doesn't have 1GB variant */
+ alloc-ranges = <0 0xc0000000 0 0x3c000000>;
+ size = <0 0x3c000000>;
+ linux,cma-default;
+ reusable;
+ };
+ };
+
+ sound-wm8904 {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&codec_dai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&codec_dai>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,name = "wm8904-audio";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "IN1L", "Microphone Jack",
+ "IN1R", "Microphone Jack";
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Headphone", "Headphone Jack",
+ "Line", "Line In Jack";
+
+ codec_dai: simple-audio-card,codec {
+ sound-dai = <&wm8904>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&esai0>;
+ };
+ };
+};
+
+&acm {
+ status = "okay";
+};
+
+&asrc0 {
+ fsl,asrc-rate = <48000>;
+ status = "okay";
+};
+
+&asrc1 {
+ fsl,asrc-rate = <48000>;
+ status = "okay";
+};
+
+&cm41_intmux {
+ status = "okay";
+};
+
+&esai0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_esai0>;
+ assigned-clocks = <&acm IMX_ADMA_ACM_ESAI0_MCLK_SEL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&esai0_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-parents = <&aud_pll_div0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <0>, <786432000>, <49152000>, <12288000>, <49152000>;
+ #sound-dai-cells = <0>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ /*
+ * The required RGMII TX and RX 2ns delays are implemented directly
+ * in hardware via passive delay elements on the SOM PCB.
+ * No delay configuration is needed in software via PHY driver.
+ */
+ phy-mode = "rgmii";
+ phy-handle = <ðphy0>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <4>;
+ reset-gpios = <&lsio_gpio2 28 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <20000>;
+ vddio-supply = <®_phy_vddio>;
+ };
+ };
+};
+
+&gpio0_mipi_csi0 {
+ status = "disabled";
+};
+
+&gpio0_mipi_csi1 {
+ status = "disabled";
+};
+
+&i2c0 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c0>;
+ status = "okay";
+
+ wm8904: codec@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ #sound-dai-cells = <0>;
+ clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "mclk";
+ assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
+ <&mclkout0_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <786432000>, <49152000>, <12288000>, <12288000>;
+ AVDD-supply = <®_audio_supply>;
+ CPVDD-supply = <®_audio_supply>;
+ DBVDD-supply = <®_audio_supply>;
+ DCVDD-supply = <®_audio_supply>;
+ MICVDD-supply = <®_audio_supply>;
+ wlf,drc-cfg-names = "default", "peaklimiter", "tradition",
+ "soft", "music";
+ /*
+ * Config registers per name, respectively:
+ * KNEE_IP = 0, KNEE_OP = 0, HI_COMP = 1, LO_COMP = 1
+ * KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1
+ * KNEE_IP = -42, KNEE_OP = -3, HI_COMP = 0, LO_COMP = 1
+ * KNEE_IP = -45, KNEE_OP = -9, HI_COMP = 1/8, LO_COMP = 1
+ * KNEE_IP = -30, KNEE_OP = -10.5, HI_COMP = 1/4, LO_COMP = 1
+ */
+ wlf,drc-cfg-regs = /bits/ 16 <0x01af 0x3248 0x0000 0x0000>,
+ /bits/ 16 <0x04af 0x324b 0x0010 0x0408>,
+ /bits/ 16 <0x04af 0x324b 0x0028 0x0704>,
+ /bits/ 16 <0x04af 0x324b 0x0018 0x078c>,
+ /bits/ 16 <0x04af 0x324b 0x0010 0x050e>;
+ /* GPIO1 = DMIC_CLK, don't touch others */
+ wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>;
+ };
+};
+
+/* Bluetooth */
+&lpuart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpuart1>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&mu_m0{
+ status = "okay";
+};
+
+&mu1_m0{
+ status = "okay";
+};
+
+&mu2_m0{
+ status = "okay";
+};
+
+&rtc {
+ status = "disabled";
+};
+
+&sai6 {
+ assigned-clocks = <&acm IMX_ADMA_ACM_SAI6_MCLK_SEL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai6_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-parents = <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <0>, <786432000>, <98304000>, <12288000>, <98304000>;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
+&sai7 {
+ assigned-clocks = <&acm IMX_ADMA_ACM_SAI7_MCLK_SEL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_PLL>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_SLV_BUS>,
+ <&clk IMX_SC_R_AUDIO_PLL_1 IMX_SC_PM_CLK_MST_BUS>,
+ <&sai7_lpcg IMX_LPCG_CLK_4>;
+ assigned-clock-parents = <&aud_pll_div1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clock-rates = <0>, <786432000>, <98304000>, <12288000>, <98304000>;
+ fsl,sai-asynchronous;
+ status = "okay";
+};
+
+&thermal_zones {
+ pmic-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <2000>;
+ thermal-sensors = <&tsens IMX_SC_R_PMIC_0>;
+ trips {
+ pmic_alert0: trip0 {
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ pmic_crit0: trip1 {
+ temperature = <125000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&pmic_alert0>;
+ cooling-device = <&A53_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&A53_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+};
+
+/* eMMC */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+/* WIFI */
+&usdhc3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_wifi>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>, <&pinctrl_wifi>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>, <&pinctrl_wifi>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ brcmf: wifi@1 {
+ compatible = "brcm,bcm4329-fmac";
+ reg = <1>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ pinctrl_esai0: esai0grp {
+ fsl,pins = <
+ IMX8QM_ESAI0_FSR_AUD_ESAI0_FSR 0xc6000040
+ IMX8QM_ESAI0_FST_AUD_ESAI0_FST 0xc6000040
+ IMX8QM_ESAI0_SCKR_AUD_ESAI0_SCKR 0xc6000040
+ IMX8QM_ESAI0_SCKT_AUD_ESAI0_SCKT 0xc6000040
+ IMX8QM_ESAI0_TX0_AUD_ESAI0_TX0 0xc6000040
+ IMX8QM_ESAI0_TX5_RX0_AUD_ESAI0_TX5_RX0 0xc6000040
+ IMX8QM_MCLK_OUT0_AUD_ACM_MCLK_OUT0 0xc600004c
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ IMX8QM_ENET0_MDC_CONN_ENET0_MDC 0x06000048
+ IMX8QM_ENET0_MDIO_CONN_ENET0_MDIO 0x06000048
+ IMX8QM_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL 0x06000048
+ IMX8QM_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC 0x06000048
+ IMX8QM_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0 0x06000048
+ IMX8QM_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1 0x06000048
+ IMX8QM_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2 0x06000048
+ IMX8QM_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3 0x06000048
+ IMX8QM_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC 0x06000048
+ IMX8QM_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL 0x06000048
+ IMX8QM_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0 0x06000048
+ IMX8QM_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1 0x06000048
+ IMX8QM_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2 0x06000048
+ IMX8QM_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3 0x06000048
+ IMX8QM_ESAI0_TX2_RX3_LSIO_GPIO2_IO28 0x06000028
+ >;
+ };
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ IMX8QM_ESAI1_FSR_LSIO_GPIO2_IO04 0x00000041
+ IMX8QM_ESAI1_FST_LSIO_GPIO2_IO05 0x00000041
+ IMX8QM_ESAI1_SCKR_LSIO_GPIO2_IO06 0x00000041
+ IMX8QM_ESAI1_SCKT_LSIO_GPIO2_IO07 0x00000041
+ IMX8QM_SPDIF0_EXT_CLK_LSIO_GPIO2_IO16 0x00000041
+ >;
+ };
+
+ pinctrl_i2c0: i2c0grp {
+ fsl,pins = <
+ IMX8QM_HDMI_TX0_TS_SCL_DMA_I2C0_SCL 0xc6000020
+ IMX8QM_HDMI_TX0_TS_SDA_DMA_I2C0_SDA 0xc6000020
+ >;
+ };
+
+ pinctrl_lpuart1: lpuart1grp {
+ fsl,pins = <
+ IMX8QM_UART1_RX_DMA_UART1_RX 0x06000020
+ IMX8QM_UART1_TX_DMA_UART1_TX 0x06000020
+ IMX8QM_UART1_CTS_B_DMA_UART1_RTS_B 0x06000020
+ IMX8QM_UART1_RTS_B_DMA_UART1_CTS_B 0x06000020
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000041
+ IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD 0x00000021
+ IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000021
+ IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000021
+ IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000021
+ IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000021
+ IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4 0x00000021
+ IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5 0x00000021
+ IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6 0x00000021
+ IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7 0x00000021
+ IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE 0x06000041
+ IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x00000021
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
+ fsl,pins = <
+ IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000040
+ IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD 0x00000020
+ IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000020
+ IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000020
+ IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000020
+ IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000020
+ IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4 0x00000020
+ IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5 0x00000020
+ IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6 0x00000020
+ IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7 0x00000020
+ IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE 0x06000040
+ IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x00000020
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <
+ IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK 0x06000040
+ IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD 0x00000020
+ IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0 0x00000020
+ IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1 0x00000020
+ IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2 0x00000020
+ IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3 0x00000020
+ IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4 0x00000020
+ IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5 0x00000020
+ IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6 0x00000020
+ IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7 0x00000020
+ IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE 0x06000040
+ IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B 0x00000020
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ IMX8QM_USDHC2_CLK_CONN_USDHC2_CLK 0x06000041
+ IMX8QM_USDHC2_CMD_CONN_USDHC2_CMD 0x00000021
+ IMX8QM_USDHC2_DATA0_CONN_USDHC2_DATA0 0x00000021
+ IMX8QM_USDHC2_DATA1_CONN_USDHC2_DATA1 0x00000021
+ IMX8QM_USDHC2_DATA2_CONN_USDHC2_DATA2 0x00000021
+ IMX8QM_USDHC2_DATA3_CONN_USDHC2_DATA3 0x00000021
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3100mhzgrp {
+ fsl,pins = <
+ IMX8QM_USDHC2_CLK_CONN_USDHC2_CLK 0x06000040
+ IMX8QM_USDHC2_CMD_CONN_USDHC2_CMD 0x00000020
+ IMX8QM_USDHC2_DATA0_CONN_USDHC2_DATA0 0x00000020
+ IMX8QM_USDHC2_DATA1_CONN_USDHC2_DATA1 0x00000020
+ IMX8QM_USDHC2_DATA2_CONN_USDHC2_DATA2 0x00000020
+ IMX8QM_USDHC2_DATA3_CONN_USDHC2_DATA3 0x00000020
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ IMX8QM_USDHC2_CLK_CONN_USDHC2_CLK 0x06000040
+ IMX8QM_USDHC2_CMD_CONN_USDHC2_CMD 0x00000020
+ IMX8QM_USDHC2_DATA0_CONN_USDHC2_DATA0 0x00000020
+ IMX8QM_USDHC2_DATA1_CONN_USDHC2_DATA1 0x00000020
+ IMX8QM_USDHC2_DATA2_CONN_USDHC2_DATA2 0x00000020
+ IMX8QM_USDHC2_DATA3_CONN_USDHC2_DATA3 0x00000020
+ >;
+ };
+
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ /* GPIOs used by user space WiFi init */
+ IMX8QM_SCU_GPIO0_07_SCU_DSC_RTC_CLOCK_OUTPUT_32K 0xc600004c
+ IMX8QM_SCU_GPIO0_03_LSIO_GPIO0_IO31 0x06000021
+ IMX8QM_SCU_GPIO0_02_LSIO_GPIO0_IO30 0x00000021
+ IMX8QM_QSPI1A_DATA0_LSIO_GPIO4_IO26 0x00000021
+ >;
+ };
+};
--
2.47.3
^ permalink raw reply related
* [PATCH v6 1/3] dt-bindings: arm: fsl: add Variscite VAR-SOM-MX8 QuadMax Boards
From: Stefano Radaelli @ 2026-07-17 10:29 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Daniel Baluta, Josua Mayer,
Alexander Stein, Ernest Van Hoecke, Maud Spierings,
Francesco Dolcini, Hugo Villeneuve, Krzysztof Kozlowski
In-Reply-To: <cover.1784284092.git.stefano.r@variscite.com>
From: Stefano Radaelli <stefano.r@variscite.com>
Add DT compatible strings for Variscite VAR-SOM-MX8 QuadMax SoM and
Variscite Symphony development carrier Board.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Stefano Radaelli <stefano.r@variscite.com>
---
v5->v6:
-
v4->v5:
-
v3->v4:
-
v2->v3:
-
v1->v2:
-
Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 7b57a6ee1b50..52f08bc1f8ea 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1393,6 +1393,12 @@ properties:
- fsl,imx8qm-mek-revd # i.MX8QM MEK Rev D Board
- const: fsl,imx8qm
+ - description: i.MX8QM Variscite VAR-SOM-MX8 based Boards
+ items:
+ - const: variscite,var-som-imx8qm-symphony
+ - const: variscite,var-som-imx8qm
+ - const: fsl,imx8qm
+
- description: i.MX8QM Boards with Toradex Apalis iMX8 Modules
items:
- enum:
--
2.47.3
^ permalink raw reply related
* [PATCH v6 0/3] Add support for Variscite VAR-SOM-MX8QM and Symphony board
From: Stefano Radaelli @ 2026-07-17 10:29 UTC (permalink / raw)
To: linux-kernel, devicetree, imx, linux-arm-kernel
Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Daniel Baluta, Josua Mayer,
Alexander Stein, Ernest Van Hoecke, Maud Spierings,
Francesco Dolcini, Hugo Villeneuve
This patch series adds support for the Variscite VAR-SOM-MX8 QuadMax
system on module and the Symphony carrier board.
The series includes:
- SOM device tree with on-module peripherals
- Symphony carrier board device tree with board-specific features
The implementation follows the standard SOM + carrier board pattern
where the SOM dtsi contains only peripherals mounted on the module,
while carrier-specific interfaces are enabled in the board dts.
v5->v6:
- Fix regulator typo
v4->v5:
- Fix sai7 clock
- Fix codec regulator voltage
v3->v4:
- Fix sai peripherals clocks
- Add comment to clarify 1GB variant
v2->v3:
- Fix led typo
- Moved reset-gpios in pciea_port0
- Removed wrong captouch pinctrl gpio
v1->v2:
- Added non-removable property to usdhc3
- Removed unused fec gpio pinctrl
- Fix ptn5150 interrupt
- Fix ecspi1 cs gpio
Stefano Radaelli (3):
dt-bindings: arm: fsl: add Variscite VAR-SOM-MX8 QuadMax Boards
arm64: dts: freescale: Add support for Variscite VAR-SOM-MX8 QuadMax
arm64: dts: imx8qm-var-som: Add support for Variscite Symphony board
.../devicetree/bindings/arm/fsl.yaml | 6 +
arch/arm64/boot/dts/freescale/Makefile | 1 +
.../dts/freescale/imx8qm-var-som-symphony.dts | 490 ++++++++++++++++
.../boot/dts/freescale/imx8qm-var-som.dtsi | 531 ++++++++++++++++++
4 files changed, 1028 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/imx8qm-var-som-symphony.dts
create mode 100644 arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi
base-commit: d089adef10f380cbdf65cbb87a59a9aab86cb0d2
prerequisite-patch-id: 0996915f031a1d899202c5fba75a969d6ce2a53d
prerequisite-patch-id: dbed47ecb907f6b7f7e284c5c1a3c325566eafd7
prerequisite-patch-id: c758aa296e6effc94c30449cc7e4773f0ae02914
prerequisite-patch-id: 31784fa7a3ee5c178b2f1ffa97c1dd7c1d3d898a
prerequisite-patch-id: 5810f43cde9c24ee318d680c1852b3ded18f3aa0
prerequisite-patch-id: 012c9c8ba4e290532a1b7f8642274b7c5f252e03
prerequisite-patch-id: a57d576be42d5061bba453f0d5960132be55a1ff
prerequisite-patch-id: e34a75fb6f7e01455dd5ca734dacad66b12de06c
prerequisite-patch-id: cc7abadd0354d14bad0cac1fbacda14ab9d4e02b
prerequisite-patch-id: c0276686c0247cb2385c56b96cbfd6de5128415c
prerequisite-patch-id: 100c47538870af63194b407fae06183fee85fc09
prerequisite-patch-id: 3a3b3e40f5fba785857091dda909d22bfc5e2d0e
--
2.47.3
^ permalink raw reply
* Re: [RFC PATCH 7/9] accel/rocket: add RK3576 NPU (RKNN) support
From: Chaoyi Chen @ 2026-07-17 10:29 UTC (permalink / raw)
To: Jiaxing Hu, tomeu, heiko, robh, krzk+dt, conor+dt, joro, will,
robin.murphy, ulfh, p.zabel, ogabbay
Cc: dri-devel, linux-rockchip, iommu, linux-pm, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260717085220.3212274-8-gahing@gahingwoo.com>
Hello Jiaxing,
On 7/17/2026 4:50 PM, Jiaxing Hu wrote:
> Add RK3576 support to the rocket DRM accelerator driver (used with the
> Mesa Teflon TFLite delegate).
>
> - match rockchip,rk3576-rknn-core; iterate its nodes at probe
> - add named clock IDs (aclk/hclk/npu/pclk) and the CBUF clock domain
> (ACLK/HCLK_RKNN_CBUF); the CNA fills the CBUF and CORE reads from it,
> so the compute path stalls if those clocks are not held for a job
> - guard rocket_job_timedout() MMIO behind pm_runtime_active()
> - hrtimer completion poll: OP_EN never clears on RK3576 (unlike
> RK3588), so poll INTERRUPT_RAW_STATUS PC_DONE bits instead
This doesn't look like a correct implementation.
> - map the DPU (0x4000) and DPU_RDMA (0x5000) blocks and pre-arm them
> - attach both NPU power domains (PD_NPU0 + PD_NPU1): the CBUF->CMAC
> read path is only fully powered with NPU1 up
>
> Tested on a Radxa ROCK 4D: the NPU probes, powers on, brings up its
> IOMMUs and runs submitted jobs to completion. Full multi-layer inference
> is not yet correct on this SoC (only the first operation per power
> session produces valid output); see the cover letter.
>
> Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>
> ---
> drivers/accel/rocket/rocket_core.c | 43 +++++++-
> drivers/accel/rocket/rocket_core.h | 22 +++-
> drivers/accel/rocket/rocket_device.c | 4 +
> drivers/accel/rocket/rocket_drv.c | 1 +
> drivers/accel/rocket/rocket_job.c | 154 +++++++++++++++++++++------
> 5 files changed, 187 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/accel/rocket/rocket_core.c b/drivers/accel/rocket/rocket_core.c
> index b3b2fa9ba..7b0c48e4d 100644
> --- a/drivers/accel/rocket/rocket_core.c
> +++ b/drivers/accel/rocket/rocket_core.c
> @@ -8,6 +8,7 @@
> #include <linux/err.h>
> #include <linux/iommu.h>
> #include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> #include <linux/pm_runtime.h>
> #include <linux/reset.h>
>
> @@ -22,12 +23,23 @@ int rocket_core_init(struct rocket_core *core)
> int err = 0;
>
> core->resets[0].id = "srst_a";
> - core->resets[1].id = "srst_h";
> err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets),
> core->resets);
> if (err)
> return dev_err_probe(dev, err, "failed to get resets for core %d\n", core->index);
>
> + core->clks[0].id = "aclk";
> + core->clks[1].id = "hclk";
> + core->clks[2].id = "npu";
> + core->clks[3].id = "pclk";
> + /*
> + * RK3576: the CBUF (convolution buffer) has its own clock domain. The CNA
> + * fills the CBUF and CORE reads from it; without these the compute path
> + * stalls after loading one slice (RDMA, which bypasses the CBUF, still
> + * runs). The vendor keeps all NPU clocks on whenever powered.
> + */
> + core->clks[4].id = "aclk_cbuf";
> + core->clks[5].id = "hclk_cbuf";
> err = devm_clk_bulk_get(dev, ARRAY_SIZE(core->clks), core->clks);
> if (err)
> return dev_err_probe(dev, err, "failed to get clocks for core %d\n", core->index);
> @@ -50,6 +62,18 @@ int rocket_core_init(struct rocket_core *core)
> return PTR_ERR(core->core_iomem);
> }
>
> + core->dpu_iomem = devm_platform_ioremap_resource_byname(pdev, "dpu");
> + if (IS_ERR(core->dpu_iomem)) {
> + dev_warn(dev, "no DPU registers; DPU S_POINTER won't be pre-armed\n");
> + core->dpu_iomem = NULL;
> + }
> +
> + core->dpu_rdma_iomem = devm_platform_ioremap_resource_byname(pdev, "dpu_rdma");
> + if (IS_ERR(core->dpu_rdma_iomem)) {
> + dev_warn(dev, "no DPU_RDMA registers; DPU_RDMA S_POINTER won't be pre-armed\n");
> + core->dpu_rdma_iomem = NULL;
> + }
> +
> dma_set_max_seg_size(dev, UINT_MAX);
>
> err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
> @@ -65,6 +89,23 @@ int rocket_core_init(struct rocket_core *core)
> return err;
> }
>
> + /*
> + * RK3576: the NPU spans TWO power domains (PD_NPU0 + PD_NPU1). The vendor
> + * powers BOTH from its single NPU node even when computing on one core --
> + * the CBUF->CMAC read path only works fully with NPU1 powered. The board DT
> + * lists both power-domains on rknn_core_0; a multi-PD device skips the
> + * driver-core single-PD auto-attach, so attach the list explicitly. With
> + * one PD in DT this is a no-op (returns 1) and behaves as before.
> + */
> + {
> + struct dev_pm_domain_list *pd_list;
> +
> + err = devm_pm_domain_attach_list(dev, NULL, &pd_list);
> + if (err < 0)
> + return dev_err_probe(dev, err,
> + "failed to attach NPU power domains\n");
> + }
> +
> pm_runtime_use_autosuspend(dev);
>
> /*
> diff --git a/drivers/accel/rocket/rocket_core.h b/drivers/accel/rocket/rocket_core.h
> index f6d738285..e959b26dd 100644
> --- a/drivers/accel/rocket/rocket_core.h
> +++ b/drivers/accel/rocket/rocket_core.h
> @@ -6,6 +6,7 @@
>
> #include <drm/gpu_scheduler.h>
> #include <linux/clk.h>
> +#include <linux/hrtimer.h>
> #include <linux/io.h>
> #include <linux/mutex_types.h>
> #include <linux/reset.h>
> @@ -27,6 +28,16 @@
> #define rocket_core_writel(core, reg, value) \
> writel(value, (core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS)
>
> +#define rocket_dpu_readl(core, reg) \
> + readl((core)->dpu_iomem + (REG_DPU_##reg) - REG_DPU_S_STATUS)
> +#define rocket_dpu_writel(core, reg, value) \
> + writel(value, (core)->dpu_iomem + (REG_DPU_##reg) - REG_DPU_S_STATUS)
> +
> +#define rocket_dpu_rdma_readl(core, reg) \
> + readl((core)->dpu_rdma_iomem + (REG_DPU_RDMA_##reg) - REG_DPU_RDMA_RDMA_S_STATUS)
> +#define rocket_dpu_rdma_writel(core, reg, value) \
> + writel(value, (core)->dpu_rdma_iomem + (REG_DPU_RDMA_##reg) - REG_DPU_RDMA_RDMA_S_STATUS)
> +
Where are these macros used?
> struct rocket_core {
> struct device *dev;
> struct rocket_device *rdev;
> @@ -36,8 +47,10 @@ struct rocket_core {
> void __iomem *pc_iomem;
> void __iomem *cna_iomem;
> void __iomem *core_iomem;
> - struct clk_bulk_data clks[4];
> - struct reset_control_bulk_data resets[2];
> + void __iomem *dpu_iomem;
> + void __iomem *dpu_rdma_iomem;
> + struct clk_bulk_data clks[6];
> + struct reset_control_bulk_data resets[1];
>
> struct iommu_group *iommu_group;
>
> @@ -52,6 +65,11 @@ struct rocket_core {
> atomic_t pending;
> } reset;
>
> + /* RK3576 has no completion IRQ; poll for PC_DONE via hrtimer. */
> + struct hrtimer poll_timer;
> + struct work_struct poll_work;
> + atomic_t poll_active;
> +
> struct drm_gpu_scheduler sched;
> u64 fence_context;
> u64 emit_seqno;
> diff --git a/drivers/accel/rocket/rocket_device.c b/drivers/accel/rocket/rocket_device.c
> index 46e6ee1e7..bfb00f967 100644
> --- a/drivers/accel/rocket/rocket_device.c
> +++ b/drivers/accel/rocket/rocket_device.c
> @@ -31,6 +31,10 @@ struct rocket_device *rocket_device_init(struct platform_device *pdev,
> if (of_device_is_available(core_node))
> num_cores++;
>
> + for_each_compatible_node(core_node, NULL, "rockchip,rk3576-rknn-core")
> + if (of_device_is_available(core_node))
> + num_cores++;
> +
> rdev->cores = devm_kcalloc(dev, num_cores, sizeof(*rdev->cores), GFP_KERNEL);
> if (!rdev->cores)
> return ERR_PTR(-ENOMEM);
> diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/rocket_drv.c
> index 8bbbce594..8f6a02d50 100644
> --- a/drivers/accel/rocket/rocket_drv.c
> +++ b/drivers/accel/rocket/rocket_drv.c
> @@ -215,6 +215,7 @@ static void rocket_remove(struct platform_device *pdev)
>
> static const struct of_device_id dt_match[] = {
> { .compatible = "rockchip,rk3588-rknn-core" },
> + { .compatible = "rockchip,rk3576-rknn-core" },
> {}
> };
> MODULE_DEVICE_TABLE(of, dt_match);
> diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
> index 2f1861f96..94461bf71 100644
> --- a/drivers/accel/rocket/rocket_job.c
> +++ b/drivers/accel/rocket/rocket_job.c
> @@ -7,6 +7,7 @@
> #include <drm/drm_file.h>
> #include <drm/drm_gem.h>
> #include <drm/rocket_accel.h>
> +#include <linux/hrtimer.h>
> #include <linux/interrupt.h>
> #include <linux/iommu.h>
> #include <linux/platform_device.h>
> @@ -20,6 +21,16 @@
>
> #define JOB_TIMEOUT_MS 500
>
> +/*
> + * RK3576: INTERRUPT_MASK bits 28-29 are read-only (hardware rejects the write),
> + * so the PC_DONE completion signal cannot be routed to the GIC via the normal
> + * interrupt-mask path. We poll OPERATION_ENABLE every RK3576_POLL_INTERVAL_NS
> + * instead of waiting for a completion IRQ.
> + */
> +#define PC_INTERRUPT_MASK_RK3576_PC_DONE_0 0x10000000u
> +#define PC_INTERRUPT_MASK_RK3576_PC_DONE_1 0x20000000u
> +#define RK3576_POLL_INTERVAL_NS 1000000LL /* 1 ms */
> +
> static struct rocket_job *
> to_rocket_job(struct drm_sched_job *sched_job)
> {
> @@ -137,8 +148,21 @@ static void rocket_job_hw_submit(struct rocket_core *core, struct rocket_job *jo
> rocket_pc_writel(core, REGISTER_AMOUNTS,
> PC_REGISTER_AMOUNTS_PC_DATA_AMOUNT((task->regcmd_count + 1) / 2 - 1));
>
> - rocket_pc_writel(core, INTERRUPT_MASK, PC_INTERRUPT_MASK_DPU_0 | PC_INTERRUPT_MASK_DPU_1);
> - rocket_pc_writel(core, INTERRUPT_CLEAR, PC_INTERRUPT_CLEAR_DPU_0 | PC_INTERRUPT_CLEAR_DPU_1);
> + /* Enable DMA-error interrupts; PC_DONE (bits 28-29) is polled, see above. */
> + rocket_pc_writel(core, INTERRUPT_MASK,
> + PC_INTERRUPT_MASK_DPU_0 | PC_INTERRUPT_MASK_DPU_1 |
> + PC_INTERRUPT_MASK_CORE_0 | PC_INTERRUPT_MASK_CORE_1 |
> + PC_INTERRUPT_MASK_PPU_0 | PC_INTERRUPT_MASK_PPU_1 |
> + PC_INTERRUPT_MASK_CNA_CSC_0 | PC_INTERRUPT_MASK_CNA_CSC_1 |
> + PC_INTERRUPT_MASK_DMA_READ_ERROR |
> + PC_INTERRUPT_MASK_DMA_WRITE_ERROR);
> + rocket_pc_writel(core, INTERRUPT_CLEAR,
> + PC_INTERRUPT_CLEAR_DPU_0 | PC_INTERRUPT_CLEAR_DPU_1 |
> + PC_INTERRUPT_CLEAR_CORE_0 | PC_INTERRUPT_CLEAR_CORE_1 |
> + PC_INTERRUPT_CLEAR_PPU_0 | PC_INTERRUPT_CLEAR_PPU_1 |
> + PC_INTERRUPT_CLEAR_CNA_CSC_0 | PC_INTERRUPT_CLEAR_CNA_CSC_1 |
> + PC_INTERRUPT_MASK_RK3576_PC_DONE_0 |
> + PC_INTERRUPT_MASK_RK3576_PC_DONE_1);
>
> rocket_pc_writel(core, TASK_CON, PC_TASK_CON_RESERVED_0(1) |
> PC_TASK_CON_TASK_COUNT_CLEAR(1) |
> @@ -149,7 +173,9 @@ static void rocket_job_hw_submit(struct rocket_core *core, struct rocket_job *jo
>
> rocket_pc_writel(core, OPERATION_ENABLE, PC_OPERATION_ENABLE_OP_EN(1));
>
> - dev_dbg(core->dev, "Submitted regcmd at 0x%llx to core %d", task->regcmd, core->index);
> + atomic_set(&core->poll_active, 1);
> + hrtimer_start(&core->poll_timer, ns_to_ktime(RK3576_POLL_INTERVAL_NS),
> + HRTIMER_MODE_REL);
> }
>
> static int rocket_acquire_object_fences(struct drm_gem_object **bos,
> @@ -326,56 +352,99 @@ static struct dma_fence *rocket_job_run(struct drm_sched_job *sched_job)
> return fence;
> }
>
> +static void rocket_job_handle_irq(struct rocket_core *core);
> +
> +static enum hrtimer_restart rocket_poll_timer_fn(struct hrtimer *timer)
> +{
> + struct rocket_core *core = container_of(timer, struct rocket_core, poll_timer);
> +
> + if (!atomic_read(&core->poll_active))
> + return HRTIMER_NORESTART;
> +
> + /*
> + * On RK3576, OPERATION_ENABLE is not cleared by hardware on completion;
> + * check INTERRUPT_RAW_STATUS bits 28-29 (PC_DONE_0/1) instead.
> + */
> + if (rocket_pc_readl(core, OPERATION_ENABLE) == 0 ||
> + (rocket_pc_readl(core, INTERRUPT_RAW_STATUS) &
> + (PC_INTERRUPT_MASK_RK3576_PC_DONE_0 |
> + PC_INTERRUPT_MASK_RK3576_PC_DONE_1))) {
> + atomic_set(&core->poll_active, 0);
> + schedule_work(&core->poll_work);
> + return HRTIMER_NORESTART;
> + }
> +
> + hrtimer_forward_now(timer, ns_to_ktime(RK3576_POLL_INTERVAL_NS));
> + return HRTIMER_RESTART;
> +}
> +
> +static void rocket_poll_work_fn(struct work_struct *work)
> +{
> + struct rocket_core *core = container_of(work, struct rocket_core, poll_work);
> +
> + rocket_job_handle_irq(core);
> +}
> +
> static void rocket_job_handle_irq(struct rocket_core *core)
> {
> + struct rocket_job *job;
> +
> + /* Stop the completion poll — we're handling it now. */
> + atomic_set(&core->poll_active, 0);
> + hrtimer_cancel(&core->poll_timer);
> +
> pm_runtime_mark_last_busy(core->dev);
>
> rocket_pc_writel(core, OPERATION_ENABLE, 0x0);
> - rocket_pc_writel(core, INTERRUPT_CLEAR, 0x1ffff);
> -
> - scoped_guard(mutex, &core->job_lock)
> - if (core->in_flight_job) {
> - if (core->in_flight_job->next_task_idx < core->in_flight_job->task_count) {
> - rocket_job_hw_submit(core, core->in_flight_job);
> - return;
> - }
> -
> - iommu_detach_group(NULL, iommu_group_get(core->dev));
> - dma_fence_signal(core->in_flight_job->done_fence);
> - pm_runtime_put_autosuspend(core->dev);
> - core->in_flight_job = NULL;
> + rocket_pc_writel(core, INTERRUPT_CLEAR,
> + 0x1ffff |
> + PC_INTERRUPT_MASK_RK3576_PC_DONE_0 |
> + PC_INTERRUPT_MASK_RK3576_PC_DONE_1);
> +
> + scoped_guard(mutex, &core->job_lock) {
> + job = core->in_flight_job;
> + if (!job)
> + return;
> +
> + if (job->next_task_idx < job->task_count) {
> + rocket_job_hw_submit(core, job);
> + return;
> }
> +
> + iommu_detach_group(job->domain->domain, core->iommu_group);
> + dma_fence_signal(job->done_fence);
> + pm_runtime_put_autosuspend(core->dev);
> + core->in_flight_job = NULL;
> + }
> }
>
> static void
> rocket_reset(struct rocket_core *core, struct drm_sched_job *bad)
> {
> + struct rocket_job *job;
> +
> if (!atomic_read(&core->reset.pending))
> return;
>
> + atomic_set(&core->poll_active, 0);
> + hrtimer_cancel(&core->poll_timer);
> + cancel_work(&core->poll_work);
> +
> drm_sched_stop(&core->sched, bad);
>
> - /*
> - * Remaining interrupts have been handled, but we might still have
> - * stuck jobs. Let's make sure the PM counters stay balanced by
> - * manually calling pm_runtime_put_noidle().
> - */
> scoped_guard(mutex, &core->job_lock) {
> - if (core->in_flight_job)
> + job = core->in_flight_job;
> + if (job) {
> pm_runtime_put_noidle(core->dev);
> -
> - iommu_detach_group(NULL, core->iommu_group);
> -
> - core->in_flight_job = NULL;
> + iommu_detach_group(job->domain->domain, core->iommu_group);
> + core->in_flight_job = NULL;
> + }
> }
>
> - /* Proceed with reset now. */
> rocket_core_reset(core);
>
> - /* NPU has been reset, we can clear the reset pending bit. */
> atomic_set(&core->reset.pending, 0);
>
> - /* Restart the scheduler */
> drm_sched_start(&core->sched, 0);
> }
>
> @@ -385,7 +454,14 @@ static enum drm_gpu_sched_stat rocket_job_timedout(struct drm_sched_job *sched_j
> struct rocket_device *rdev = job->rdev;
> struct rocket_core *core = sched_to_core(rdev, sched_job->sched);
>
> - dev_err(core->dev, "NPU job timed out");
> + if (pm_runtime_active(core->dev))
> + dev_err(core->dev,
> + "NPU job timed out: RAW_STATUS=0x%08x MASK=0x%08x OP_EN=0x%08x\n",
> + rocket_pc_readl(core, INTERRUPT_RAW_STATUS),
> + rocket_pc_readl(core, INTERRUPT_MASK),
> + rocket_pc_readl(core, OPERATION_ENABLE));
> + else
> + dev_err(core->dev, "NPU job timed out (device not active)\n");
>
> atomic_set(&core->reset.pending, 1);
> rocket_reset(core, sched_job);
> @@ -420,14 +496,16 @@ static irqreturn_t rocket_job_irq_handler(int irq, void *data)
> {
> struct rocket_core *core = data;
> u32 raw_status = rocket_pc_readl(core, INTERRUPT_RAW_STATUS);
> + /* Only bits 0-13 (DMA errors) can raise this IRQ; PC_DONE is polled. */
> + u32 active = raw_status & 0x3fff;
> +
> + if (!active)
> + return IRQ_NONE;
>
> WARN_ON(raw_status & PC_INTERRUPT_RAW_STATUS_DMA_READ_ERROR);
> WARN_ON(raw_status & PC_INTERRUPT_RAW_STATUS_DMA_WRITE_ERROR);
>
> - if (!(raw_status & PC_INTERRUPT_RAW_STATUS_DPU_0 ||
> - raw_status & PC_INTERRUPT_RAW_STATUS_DPU_1))
> - return IRQ_NONE;
> -
> + rocket_pc_writel(core, INTERRUPT_CLEAR, active);
> rocket_pc_writel(core, INTERRUPT_MASK, 0x0);
>
> return IRQ_WAKE_THREAD;
> @@ -445,6 +523,10 @@ int rocket_job_init(struct rocket_core *core)
> int ret;
>
> INIT_WORK(&core->reset.work, rocket_reset_work);
> + INIT_WORK(&core->poll_work, rocket_poll_work_fn);
> + hrtimer_setup(&core->poll_timer, rocket_poll_timer_fn, CLOCK_MONOTONIC,
> + HRTIMER_MODE_REL);
> + atomic_set(&core->poll_active, 0);
> spin_lock_init(&core->fence_lock);
> mutex_init(&core->job_lock);
>
> @@ -486,6 +568,10 @@ int rocket_job_init(struct rocket_core *core)
>
> void rocket_job_fini(struct rocket_core *core)
> {
> + atomic_set(&core->poll_active, 0);
> + hrtimer_cancel(&core->poll_timer);
> + cancel_work_sync(&core->poll_work);
> +
> drm_sched_fini(&core->sched);
>
> cancel_work_sync(&core->reset.work);
--
Best,
Chaoyi
^ permalink raw reply
* Re: [PATCH v8 2/8] iio: dac: ad5686: missing NULL check on match data
From: Andy Shevchenko @ 2026-07-17 10:28 UTC (permalink / raw)
To: Rodrigo Alencar
Cc: Michael Auchter, linux, linux-iio, devicetree, linux-kernel,
linux-hardening, Michael Hennerich, Jonathan Cameron,
David Lechner, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Kees Cook, Gustavo A. R. Silva,
sashiko-bot
In-Reply-To: <gy2dn5emz7sreavy6kioz27f3sx2ip6zhkgzs2uz4qzecpkrbe@zgsortof6aqn>
On Fri, Jul 17, 2026 at 10:31:26AM +0100, Rodrigo Alencar wrote:
> On 17/07/26 11:15, Andy Shevchenko wrote:
> > On Fri, Jul 17, 2026 at 07:51:35AM +0100, Rodrigo Alencar wrote:
> > > On 16/07/26 21:42, Andy Shevchenko wrote:
> > > > On Thu, Jul 16, 2026 at 01:14:18PM +0100, Rodrigo Alencar via B4 Relay wrote:
...
> > > > > struct iio_dev *indio_dev;
> > > > > int ret, i;
> > > >
> > > > Move an assignment here as well.
> > > >
> > > > chip_info = ...
> > >
> > > assignment? this is an input param validation
> >
> > Can we make sure we always get a correct one to begin with?
> > With that an assignment and check can be coupled together.
> > Also consider use -ENODATA as it's most likely comes from
> > driver_data.
>
> I suppose you are suggesting to move the check to the bus code with:
>
> info = i2c_get_match_data(i2c);
> if (!info)
> return -ENODATA;
>
> rather than here in the core/common code.
Yes! This avoids layering violation and makes the API contract cleaner.
> > > > > + if (!chip_info)
> > > > > + return -ENODEV;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [RFC PATCH 6/9] iommu/rockchip: take all DT clocks
From: Chaoyi Chen @ 2026-07-17 10:19 UTC (permalink / raw)
To: Jiaxing Hu, tomeu, heiko, robh, krzk+dt, conor+dt, joro, will,
robin.murphy, ulfh, p.zabel, ogabbay
Cc: dri-devel, linux-rockchip, iommu, linux-pm, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260717085220.3212274-7-gahing@gahingwoo.com>
Hello Jiaxing,
On 7/17/2026 4:50 PM, Jiaxing Hu wrote:
> rk_iommu only enabled a fixed {aclk,iface} pair. On the RK3576 NPU the
> MMU sits behind the CBUF/DSU gates, so writes to DTE_ADDR are silently
> dropped until those clocks run too (reads work, writes need more clocks).
> Take every clock described in the DT for the IOMMU instead of a fixed
> pair, so a platform can list the full set it needs.
>
> Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>
> ---
> drivers/iommu/rockchip-iommu.c | 30 ++++++++++--------------------
> 1 file changed, 10 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
> index ce586919b..49c841095 100644
> --- a/drivers/iommu/rockchip-iommu.c
> +++ b/drivers/iommu/rockchip-iommu.c
> @@ -93,11 +93,6 @@ struct rk_iommu_domain {
> struct iommu_domain domain;
> };
>
> -/* list of clocks required by IOMMU */
> -static const char * const rk_iommu_clocks[] = {
> - "aclk", "iface",
> -};
> -
> struct rk_iommu_ops {
> phys_addr_t (*pt_address)(u32 dte);
> u32 (*mk_dtentries)(dma_addr_t pt_dma);
> @@ -1274,25 +1269,20 @@ static int rk_iommu_probe(struct platform_device *pdev)
> iommu->reset_disabled = device_property_read_bool(dev,
> "rockchip,disable-mmu-reset");
>
> - iommu->num_clocks = ARRAY_SIZE(rk_iommu_clocks);
> - iommu->clocks = devm_kcalloc(iommu->dev, iommu->num_clocks,
> - sizeof(*iommu->clocks), GFP_KERNEL);
> - if (!iommu->clocks)
> - return -ENOMEM;
> -
> - for (i = 0; i < iommu->num_clocks; ++i)
> - iommu->clocks[i].id = rk_iommu_clocks[i];
> -
> /*
> - * iommu clocks should be present for all new devices and devicetrees
> - * but there are older devicetrees without clocks out in the wild.
> - * So clocks as optional for the time being.
> + * Take every clock the devicetree provides. Most IOMMU instances
> + * need exactly "aclk" + "iface", but e.g. the RK3576 NPU IOMMUs sit
> + * behind additional gates (CBUF/DSU) whose clocks must be running
> + * for register writes to land. Clocks stay optional because there
> + * are older devicetrees without clocks out in the wild.
> */
It does not seem necessary to modify the comments, as there are indeed
many MMUs with multiple clocks :)
> - err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
> - if (err == -ENOENT)
> + err = devm_clk_bulk_get_all(iommu->dev, &iommu->clocks);
> + if (err == -ENOENT || err == 0)
> iommu->num_clocks = 0;
err == 0 is redundant.
> - else if (err)
> + else if (err < 0)
> return err;
> + else
> + iommu->num_clocks = err;
>
> err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
> if (err)
--
Best,
Chaoyi
^ permalink raw reply
* Re: [PATCH v9 1/7] dt-bindings: clock: qcom: Move glymur TCSR to own binding
From: Qiang Yu @ 2026-07-17 10:23 UTC (permalink / raw)
To: sashiko-reviews; +Cc: conor+dt, devicetree, robh
In-Reply-To: <20260714050953.BACC51F000E9@smtp.kernel.org>
On Tue, Jul 14, 2026 at 05:09:53AM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] The newly added qcom,glymur-tcsr.yaml binding marks 17 `vdda-qref*` supply properties as unconditionally required, but existing device trees do not provide them, causing a `dtbs_check` validation regression.
> --
>
> --- Patch [1]: [PATCH v9 1/7] dt-bindings: clock: qcom: Move glymur TCSR to own binding ---
> commit 6bffb0197809346112dba264dc91035d8e1ed982
> Author: Qiang Yu <qiang.yu@oss.qualcomm.com>
>
> dt-bindings: clock: qcom: Move glymur TCSR to own binding
>
> This commit extracts the Glymur TCSR block into its own dedicated YAML binding
> file and documents the supply properties required by the QREF block. It uses
> an allOf conditional block to enforce these supplies for the qcom,glymur-tcsr
> compatible string.
>
> > diff --git a/Documentation/devicetree/bindings/clock/qcom,glymur-tcsr.yaml b/Documentation/devicetree/bindings/clock/qcom,glymur-tcsr.yaml
> > new file mode 100644
> > index 0000000000000..ec89feff89e4e
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/qcom,glymur-tcsr.yaml
> [ ... ]
> > +allOf:
> > + - if:
> > + properties:
> > + compatible:
> > + contains:
> > + const: qcom,glymur-tcsr
> > + then:
> > + required:
> > + - vdda-qrefrpt0-0p9-supply
> > + - vdda-qrefrpt1-0p9-supply
>
> [Severity: Medium]
> Does this cause a dtbs_check validation regression for existing platforms?
>
> By marking these 17 vdda-qref* supply properties as unconditionally required
> in the allOf block, validation will fail for existing device trees (such as
> arch/arm64/boot/dts/qcom/glymur.dtsi) that use the qcom,glymur-tcsr
> compatible string but do not yet provide these supplies.
>
> Would it be better to introduce these properties as optional first, or ensure
> the corresponding device tree updates are included in the same patch series
> to prevent breaking schema validation?
>
This yaml only is used by glymur and mahua so these properties only affect
them. I have provided all qref/refgen LDOs they require and did the dtb
check, no warnings or errors.
- Qiang Yu
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260713-tcsr_qref_0714-v9-0-373670ab15f9@oss.qualcomm.com?part=1
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: mmc: Add post-power-off-delay-ms property
From: Ulf Hansson @ 2026-07-17 10:21 UTC (permalink / raw)
To: Judith Mendez
Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-mmc, devicetree, linux-kernel
In-Reply-To: <20260716232641.2659710-2-jm@ti.com>
On Fri, Jul 17, 2026 at 1:26 AM Judith Mendez <jm@ti.com> wrote:
>
> Add post-power-off-delay-ms property to MMC controller common.
>
> This property shall be used to specify delay if needed after
> deasserting power during MMC power cycles.
Please clarify with some additional information from the cover-letter,
like "specify custom delays after MMC power off to work around
hardware issues such as slow RC circuites on MMC VDD rails."
>
> Signed-off-by: Judith Mendez <jm@ti.com>
> ---
> .../devicetree/bindings/mmc/mmc-controller-common.yaml | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller-common.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller-common.yaml
> index 3d7195e9461c3..3ff68d32a308f 100644
> --- a/Documentation/devicetree/bindings/mmc/mmc-controller-common.yaml
> +++ b/Documentation/devicetree/bindings/mmc/mmc-controller-common.yaml
> @@ -275,6 +275,14 @@ properties:
> not available.
> default: 10
>
> + post-power-off-delay-ms:
For mmc-pwrseq-simple we already have "power-off-delay-us", perhaps
better to re-use that name instead.
> + description:
> + The presence of this property indicates that the card requires a
> + delay (in milliseconds) after power off before the next power on.
Again, maybe something to indicate this is specific like "specify
custom delays after MMC power off to work around
hardware issues such as slow RC circuites on MMC VDD rails."
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 0
> + maximum: 10000
Are the above limits needed at all?
I suggest we add a "default: 1", as that would correspond to the
hardcoded value that the mmc core currently uses for this delay.
> +
> supports-cqe:
> $ref: /schemas/types.yaml#/definitions/flag
> description:
> --
> 2.54.0
>
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH v2 3/3] arm64: dts: qcom: monaco: enable audio ML offload memory and SMMU mappings
From: sashiko-bot @ 2026-07-17 10:13 UTC (permalink / raw)
To: Pratyush Meduri; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260717095825.3962666-4-pratyush.meduri@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The ML-related SMMU stream IDs are added to a different device's IOMMU domain (remoteproc_adsp) than the device mapping the CMA buffer (q6apmdai), leading to Stage 1 Translation Faults.
- [Medium] The commit message incorrectly documents the Stream IDs being added as 0x3060 and 0x3062, while the code adds 0x2060 and 0x2062.
- [Low] The newly added reserved-memory node uses a vendor prefix and comma (`qcom,audio-ml`), which violates standard DT node naming guidelines.
Pre-existing issues:
- [High] The `q6apmdai` driver does not initialize the DT `memory-region` property, rendering the devicetree addition inert and causing allocations to fall back to the default allocator.
--
--- Patch [3]: [PATCH v2 3/3] arm64: dts: qcom: monaco: enable audio ML offload memory and SMMU mappings ---
commit 4a8f1567e9c6cd6a5d86dc17c6731564a853e2ff
Author: Pratyush Meduri <pratyush.meduri@oss.qualcomm.com>
arm64: dts: qcom: monaco: enable audio ML offload memory and SMMU mappings
The audio ML (machine-learning) offload use case requires a contiguous,
physically addressable buffer shared with the audio DSP/SPF, and issues
DMA transactions through additional SMMU stream IDs that are not
covered by the existing ADSP mapping.
[ ... ]
> Add the ML-related stream IDs (0x3060 mask 0x9, 0x3062 mask 0x1) to the
> remoteproc_adsp iommus property in the EL2 overlay so these buffers are
> translated by the SMMU instead of being rejected.
[Severity: Medium]
The commit message documents adding stream IDs 0x3060 and 0x3062, but the code
adds 0x2060 and 0x2062. Is this a typo in the commit message?
> diff --git a/arch/arm64/boot/dts/qcom/monaco-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-el2.dtso
> index a7e3270f86090..97bb8287cec33 100644
> --- a/arch/arm64/boot/dts/qcom/monaco-el2.dtso
> +++ b/arch/arm64/boot/dts/qcom/monaco-el2.dtso
> @@ -17,7 +17,9 @@ &iris {
> };
>
> &remoteproc_adsp {
> - iommus = <&apps_smmu 0x2000 0x0>;
> + iommus = <&apps_smmu 0x2000 0x0>,
> + <&apps_smmu 0x2060 0x9>,
> + <&apps_smmu 0x2062 0x1>;
> };
[Severity: High]
Does adding the ML-related stream IDs to the remoteproc_adsp node result in
Stage 1 Translation Faults?
The memory-region is assigned to the q6apmdai device (which uses stream ID
0x2001) in monaco.dtsi. When q6apmdai allocates and DMA-maps the memory, the
mapping is created in the IOMMU domain associated with 0x2001.
By adding 0x2060 and 0x2062 to remoteproc_adsp (which uses 0x2000), the Linux
arm-smmu driver places these stream IDs into a different IOMMU domain than the
one holding the ML memory mapping. Should these stream IDs be added to the
q6apmdai node instead so they share the same IOMMU domain?
> diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
> index 64fc0d592282c..d971c0ea1b302 100644
> --- a/arch/arm64/boot/dts/qcom/monaco.dtsi
> +++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
> @@ -729,6 +729,14 @@ reserved-memory {
> #size-cells = <2>;
> ranges;
>
> + audio_cma_mem: qcom,audio-ml {
[Severity: Low]
Does this node name violate Devicetree naming conventions? Node names should
typically be generic and avoid vendor prefixes and commas, which are reserved
for compatible strings.
> + compatible = "shared-dma-pool";
> + alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
> + reusable;
> + alignment = <0x0 0x400000>;
> + size = <0x0 0x1000000>;
> + };
> +
[ ... ]
> @@ -2844,6 +2852,7 @@ q6apmbedai: bedais {
> q6apmdai: dais {
> compatible = "qcom,q6apm-dais";
> iommus = <&apps_smmu 0x2001 0x0>;
> + memory-region = <&audio_cma_mem>;
> };
[Severity: High]
This isn't a bug introduced by this patch, but will this memory-region
assignment be ignored by the q6apmdai driver?
Looking at q6apm_dai_probe() in sound/soc/qcom/qdsp6/q6apm-dai.c:
rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
if (rc < 0)
pdata->sid = -1;
else
pdata->sid = args.args[0] & SID_MASK_DEFAULT;
dev_set_drvdata(dev, pdata);
return devm_snd_soc_register_component(dev, &q6apm_fe_dai_component, NULL, 0);
The driver probe function does not call of_reserved_mem_device_init(). For a
shared-dma-pool, the driver must explicitly initialize it. Without this call,
the driver dev->cma_area remains unconfigured and memory allocations will
silently fall back to the default system CMA pool, defeating the purpose of
adding this dedicated 16MiB region.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717095825.3962666-1-pratyush.meduri@oss.qualcomm.com?part=3
^ permalink raw reply
* Re: [PATCH v4 2/2] usb: typec: ucsi: Add ITE IT8851/IT8853 Type-C PD controller driver
From: sashiko-bot @ 2026-07-17 10:12 UTC (permalink / raw)
To: Amber Kao; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260717-ucsi-itepd-v4-2-f3ba5addd0df@ite.com.tw>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Use-After-Free vulnerability in teardown sequence due to incorrect free_irq() placement.
- [High] Unhandled hardware events or I2C errors in the interrupt handler skip acknowledging the interrupt, causing an interrupt storm.
--
--- Patch [2]: [PATCH v4 2/2] usb: typec: ucsi: Add ITE IT8851/IT8853 Type-C PD controller driver ---
commit 17d94bce1f3a61576b21089ce840ef1e6562fa4c
Author: Amber Kao <amber.kao@ite.com.tw>
usb: typec: ucsi: Add ITE IT8851/IT8853 Type-C PD controller driver
This commit adds a UCSI driver for the ITE IT8851 and IT8853 I2C-based
USB Type-C Power Delivery controllers. It implements the I2C interface to
read and write UCSI commands and handles shared interrupt lines to forward
events to the UCSI core.
> diff --git a/drivers/usb/typec/ucsi/ucsi_itepd.c b/drivers/usb/typec/ucsi/ucsi_itepd.c
> new file mode 100644
> index 0000000000000..ceaadb0b3fef6
> --- /dev/null
> +++ b/drivers/usb/typec/ucsi/ucsi_itepd.c
[ ... ]
> +static int itepd_process_event(struct itepd *itepd, u32 *cci)
> +{
> + u8 msg_in[ITEPD_MSG_IN_MAX_LEN] = {};
> + __le32 le_cci;
> + u8 event, ack;
> + u8 len = 0;
> + int ret;
> +
> + mutex_lock(&itepd->event_lock);
> +
> + ret = itepd_read_reg(itepd, ITEPD_VENDOR_INT, &event, sizeof(event));
> + if (ret)
> + goto out_unlock;
> +
> + event &= ITEPD_ALERT_VDM_EVENT | ITEPD_ALERT_UCSI_EVENT;
> + if (!event) {
> + mutex_lock(&itepd->received_lock);
> + *cci = itepd->cci;
> + mutex_unlock(&itepd->received_lock);
> + ret = ITEPD_EVENT_NONE;
> + goto out_unlock;
> + }
[Severity: High]
If an unrecognized event occurs (neither VDM nor UCSI) and this path takes
the goto out_unlock, it skips writing to ITEPD_VENDOR_WC_INT to clear the
interrupt. Will this leave the interrupt line asserted and cause an
interrupt storm once the IRQ is unmasked?
> +
> + if (event & ITEPD_ALERT_UCSI_EVENT) {
> + ret = itepd_read_reg(itepd, ITEPD_UCSI_CCI_REG, &le_cci,
> + sizeof(le_cci));
> + if (ret)
> + goto out_unlock;
[Severity: High]
Similarly, if this I2C read fails (for example, if the kzalloc inside
itepd_read_reg fails), this goto out_unlock also skips acknowledging the
interrupt. Can this lead to an interrupt storm?
[ ... ]
> +static void itepd_remove(struct i2c_client *client)
> +{
> + struct itepd *itepd = i2c_get_clientdata(client);
> +
> + ucsi_unregister(itepd->ucsi);
> + free_irq(client->irq, itepd);
[Severity: High]
Could this sequence result in a use-after-free? ucsi_unregister() disables
notifications and frees ucsi->connector. If an interrupt fires or is
already pending before free_irq() is called, the threaded interrupt handler
itepd_irq_thread_fn() can run, process the event, and call
ucsi_notify_common().
In ucsi_notify_common(), this could lead to dereferencing the freed
ucsi->connector array via ucsi_connector_change(). Should the IRQ be
freed or disabled prior to unregistering UCSI?
> + ucsi_destroy(itepd->ucsi);
> +}
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717-ucsi-itepd-v4-0-f3ba5addd0df@ite.com.tw?part=2
^ permalink raw reply
* Re: [PATCH v2 2/3] arm64: dts: qcom: lemans: enable audio ML offload memory and SMMU mappings
From: sashiko-bot @ 2026-07-17 10:11 UTC (permalink / raw)
To: Pratyush Meduri; +Cc: robh, devicetree, conor+dt
In-Reply-To: <20260717095825.3962666-3-pratyush.meduri@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] IOMMU Domain Mismatch causing SMMU Translation Faults
- [Low] Device Tree Naming Anti-pattern for reserved-memory node
--
--- Patch [2]: [PATCH v2 2/3] arm64: dts: qcom: lemans: enable audio ML offload memory and SMMU mappings ---
commit 420f45475f05629508de21378a1cf7698d94040d
Author: Pratyush Meduri <pratyush.meduri@oss.qualcomm.com>
arm64: dts: qcom: lemans: enable audio ML offload memory and SMMU mappings
The audio ML offload use case requires a contiguous buffer shared with the
audio DSP, issuing DMA transactions through additional SMMU stream IDs. This
adds a dedicated shared-dma-pool CMA region wired to q6apm DAIs and maps
the ML stream IDs to the EL2 overlay remoteproc_adsp iommus property.
> diff --git a/arch/arm64/boot/dts/qcom/lemans-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-el2.dtso
> index 621ad930cf547..5b477346ef908 100644
> --- a/arch/arm64/boot/dts/qcom/lemans-el2.dtso
> +++ b/arch/arm64/boot/dts/qcom/lemans-el2.dtso
> @@ -19,7 +19,9 @@ &iris {
> };
>
> &remoteproc_adsp {
> - iommus = <&apps_smmu 0x3000 0x0>;
> + iommus = <&apps_smmu 0x3000 0x0>,
> + <&apps_smmu 0x3060 0x9>,
> + <&apps_smmu 0x3062 0x1>;
> };
[ ... ]
> diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi
> index 3b0539e27b519..0605651137846 100644
> --- a/arch/arm64/boot/dts/qcom/lemans.dtsi
> +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi
> @@ -624,6 +624,14 @@ reserved-memory {
> #size-cells = <2>;
> ranges;
>
> + audio_cma_mem: qcom,audio-ml {
[Severity: Low]
This isn't a bug, but does this node name violate Device Tree naming
conventions?
Node names are typically generic and shouldn't contain vendor prefixes or
commas unless they match the first compatible string exactly.
Could this be renamed to something like audio-ml-cma or audio-ml-mempool
instead?
> + compatible = "shared-dma-pool";
> + alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
> + reusable;
> + alignment = <0x0 0x400000>;
> + size = <0x0 0x1000000>;
> + };
> +
> sail_ss_mem: sail-ss@80000000 {
[ ... ]
> @@ -8134,6 +8142,7 @@ q6apmbedai: bedais {
> q6apmdai: dais {
> compatible = "qcom,q6apm-dais";
> iommus = <&apps_smmu 0x3001 0x0>;
> + memory-region = <&audio_cma_mem>;
> };
[Severity: High]
Will the ML engine actually be able to access this memory without triggering
SMMU translation faults?
The CMA memory region (audio_cma_mem) is assigned here to the q6apmdai
device. Consequently, allocations from this pool are mapped exclusively into
the IOMMU domain associated with q6apmdai (stream ID 0x3001).
However, the ML stream IDs (0x3060 and 0x3062) were assigned to the
remoteproc_adsp device earlier in lemans-el2.dtso:
&remoteproc_adsp {
iommus = <&apps_smmu 0x3000 0x0>,
<&apps_smmu 0x3060 0x9>,
<&apps_smmu 0x3062 0x1>;
};
Since separate platform devices with distinct iommus properties are placed
into separate IOMMU groups and domains, won't the SMMU fail to look up the
CMA memory mappings when the ML engine issues transactions using stream ID
0x3060 or 0x3062?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717095825.3962666-1-pratyush.meduri@oss.qualcomm.com?part=2
^ permalink raw reply
* Re: [PATCH v2 4/5] clk: qcom: gcc-hawi: Add support for global clock controller on Maili
From: Konrad Dybcio @ 2026-07-17 10:11 UTC (permalink / raw)
To: Taniya Das, Bjorn Andersson, Michael Turquette, Stephen Boyd,
Brian Masney, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Vivek Aknurwar
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel
In-Reply-To: <20260713-maili_initial_clock-v2-4-79548f0bb58f@oss.qualcomm.com>
On 7/13/26 11:04 AM, Taniya Das wrote:
> Add support for the global clock controller (GCC) on the Qualcomm Maili
> SoC by extending the Hawi global clock controller since Maili is identical
> to Hawi and has few additional clocks.
>
> Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
> ---
[...]
> + /*
> + * Maili-only clocks: NULL here to size the array to the highest Maili
> + * clock index.
> + */
> + [GCC_QUPV3_WRAP_5_S_AHB_CLK] = NULL,
This is unnecessary/wrong, as desc->num_clks validates the index in
qcom_cc_clk_hw_get().
Without this, we'd get an -EINVAL, with this we get a silent nullptr
Konrad
^ permalink raw reply
* Re: [PATCH v3 2/4] clocksource/drivers: Add support for the Renesas RZ/N1 timers
From: sashiko-bot @ 2026-07-17 10:08 UTC (permalink / raw)
To: Herve Codina (Schneider Electric); +Cc: wsa+renesas, devicetree, conor+dt, robh
In-Reply-To: <20260717095552.767475-3-herve.codina@bootlin.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] Off-by-one error in CPU bounds check allows out-of-bounds array access in the hotplug callback.
- [High] A 16-bit high-frequency clocksource is incorrectly flagged with CLOCK_SOURCE_SUSPEND_NONSTOP, breaking system suspend timekeeping.
- [High] Probe incorrectly returns a positive IRQ number on devm_request_irq failure.
- [High] Missing teardown callback in cpuhp_setup_state causes a Use-After-Free of clockevent devices.
- [Medium] Down-counting timer values are potentially returned directly, breaking the requirement for monotonic increasing counters.
- [Medium] Failing CPU bringup by returning an error from a CPU hotplug starting callback.
--
--- Patch [2]: [PATCH v3 2/4] clocksource/drivers: Add support for the Renesas RZ/N1 timers ---
commit 67eeb3e62e1eb246f2738740b9b5319a484b8d50
Author: Herve Codina (Schneider Electric) <herve.codina@bootlin.com>
clocksource/drivers: Add support for the Renesas RZ/N1 timers
The Renesas RZ/N1 timer block controller is the controller in charge of
timers available in the Renesas RZ/N1 SoCs family. This controller handles
8 timers: 6 16-bit timers and 2 32-bit timers.
> diff --git a/drivers/clocksource/timer-rzn1.c b/drivers/clocksource/timer-rzn1.c
> new file mode 100644
> index 0000000000000..024f01bb0227b
> --- /dev/null
> +++ b/drivers/clocksource/timer-rzn1.c
[ ... ]
> +static u64 notrace rzn1_sched_read(void)
> +{
> + return readl_relaxed(rzn1_sched_clock->base + RZN1_TIMER_CURRENT_COUNT_REG);
> +}
> +
> +static u64 rzn1_clksrc_read(struct clocksource *cs)
> +{
> + return readl_relaxed(rzn1_sched_clock->base + RZN1_TIMER_CURRENT_COUNT_REG);
> +}
[Severity: Medium]
Since RZN1_TIMER_LOAD_COUNT_REG is used earlier to set the timer period,
does this hardware act as a down-counter?
If the hardware counts downward, will returning the raw value here break the
timekeeping requirement for monotonically increasing values?
> +static struct clocksource rzn1_clocksource = {
> + .name = "rzn1_timer_clocksource",
> + .rating = 200,
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
[Severity: High]
Is it safe to flag a 16-bit clocksource with CLOCK_SOURCE_SUSPEND_NONSTOP?
Since a 16-bit counter fed by a high-frequency clock will wrap around very
quickly, will this cause massive wall time jumps if the system suspends for
longer than the wrap interval?
> + .read = rzn1_clksrc_read,
> +};
> +
> +/* Timers table where 32-bit timers will be assigned per-cpu */
> +static struct rzn1_timer *rzn1_tab_timers;
> +
> +static int rzn1_local_timer_starting_cpu(unsigned int cpu)
> +{
> + struct rzn1_timer *timer;
> +
> + if (cpu > RZN1_TIMER_NB_32BIT_TIMERS)
> + return -EINVAL;
[Severity: Medium]
Will returning an error like -EINVAL completely abort the hotplug process
for any CPU beyond the first two?
Should this return 0 instead, allowing additional CPUs to still boot online
and rely on a global broadcast timer?
[Severity: High]
Also, does the greater-than condition here have an off-by-one error?
If RZN1_TIMER_NB_32BIT_TIMERS is 2, a cpu value of 2 bypasses this check.
> +
> + timer = &rzn1_tab_timers[cpu + RZN1_TIMER_BASE_INDEX_32BIT_TIMERS];
[Severity: High]
If a cpu value of 2 bypassed the check above, will this access out of bounds?
The array is only sized for 8 elements total. Adding a cpu value of 2 to
RZN1_TIMER_BASE_INDEX_32BIT_TIMERS (which is 6) computes an index of 8.
[ ... ]
> +static int rzn1_timer_setup_timers(struct platform_device *pdev,
> + struct rzn1_timer *tab_timers,
> + unsigned int first_timer_index,
> + unsigned int last_timer_index,
> + void __iomem *base, unsigned long clock_rate)
> +{
[ ... ]
> + ret = devm_request_irq(dev, timer->ced.irq, rzn1_timer_interrupt,
> + IRQF_TIMER, timer->ced.name, timer);
> + if (ret < 0)
> + return dev_err_probe(dev, irq, "timer%u: Failed to request IRQ\n", i);
[Severity: High]
Will calling dev_err_probe() with irq return the positive IRQ number back to
the caller instead of the negative ret code?
If the driver probe returns a positive integer, won't the driver core assume
the probe succeeded despite the failure?
[ ... ]
> +static int rzn1_timer_probe_first(struct platform_device *pdev,
> + struct rzn1_timer *tab_timers,
> + void __iomem *base, unsigned long clock_rate)
> +{
[ ... ]
> + /*
> + * Second step, almost all operations that can fail have been called.
> + * Timers are ready to work. Start with the last operation that can fail,
> + * installing and invoking hotplug callbacks
> + */
> + rzn1_tab_timers = tab_timers;
> + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
> + "clockevents/rzn1/global_timer:starting",
> + rzn1_local_timer_starting_cpu, NULL);
[Severity: High]
Does passing a NULL teardown callback here leave registered clockevent
devices dangling if a subsequent step fails during probe?
If the driver fails and frees its timer structures via devres, or if a CPU
is dynamically offlined later, will this lack of teardown cause a
use-after-free in the clockevents core?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717095552.767475-1-herve.codina@bootlin.com?part=2
^ permalink raw reply
* Re: [PATCH 8/8] arm64: dts: qcom: eliza-mtp: Enable Adreno A722 GPU
From: Konrad Dybcio @ 2026-07-17 10:06 UTC (permalink / raw)
To: Akhil P Oommen, Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Will Deacon, Robin Murphy, Joerg Roedel (AMD),
Puranam V G Tejaswi, Abel Vesa, linux-arm-msm, dri-devel,
freedreno, linux-kernel, devicetree, linux-arm-kernel, iommu
In-Reply-To: <2d9d6724-a3ea-42ad-8cb3-ef08fd0882be@oss.qualcomm.com>
On 7/13/26 9:50 PM, Akhil P Oommen wrote:
> On 7/7/2026 3:53 AM, Dmitry Baryshkov wrote:
>> On Sun, Jul 05, 2026 at 01:44:23PM +0530, Akhil P Oommen wrote:
>>> From: Puranam V G Tejaswi <puranam.tejaswi@oss.qualcomm.com>
>>>
>>> Enable the Adreno A722 GPU on the Eliza MTP board and provide the zap
>>> shader firmware path.
>>>
>>> Signed-off-by: Puranam V G Tejaswi <puranam.tejaswi@oss.qualcomm.com>
>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>> ---
>>> arch/arm64/boot/dts/qcom/eliza-mtp.dts | 8 ++++++++
>>> 1 file changed, 8 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/qcom/eliza-mtp.dts b/arch/arm64/boot/dts/qcom/eliza-mtp.dts
>>> index 1374afd9d14e..b280d8e845b1 100644
>>> --- a/arch/arm64/boot/dts/qcom/eliza-mtp.dts
>>> +++ b/arch/arm64/boot/dts/qcom/eliza-mtp.dts
>>> @@ -417,6 +417,14 @@ vreg_l7k: ldo7 {
>>> };
>>> };
>>>
>>> +&gpu {
>>> + status = "okay";
>>> +};
>>> +
>>> +&gpu_zap_shader {
>>> + firmware-name = "qcom/eliza/gen70e00_zap.mbn";
>>
>> Should it be gen71700_zap.mbn?
>
> Downstream uses gen70e00_zap.mbn as this fw is shared between Eliza and
> another GPU. But, for upstream we can rename it. In linux-firmware, I
> will keep gen71700_zap.mbn as a symlink to gen70e00_zap.mbn.
Let's use the name you proposed. I mistook it for the GMU fw, which is
named differently.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH 7/8] arm64: dts: qcom: eliza: Add GPU nodes
From: Konrad Dybcio @ 2026-07-17 10:04 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Will Deacon, Robin Murphy, Joerg Roedel (AMD)
Cc: Puranam V G Tejaswi, Abel Vesa, linux-arm-msm, dri-devel,
freedreno, linux-kernel, devicetree, linux-arm-kernel, iommu
In-Reply-To: <20260705-eliza-gpu-v1-7-c9f1354dbd29@oss.qualcomm.com>
On 7/5/26 10:14 AM, Akhil P Oommen wrote:
> From: Puranam V G Tejaswi <puranam.tejaswi@oss.qualcomm.com>
>
> Adreno 722 found in Eliza chipset belongs to the A7x GEN1 family. It is
> derived from A730 and shares the same IP-level configurations: HWCG
> registers, protected registers, GBIF CX registers and gmu_cgc_mode.
> Major differences include lower cache/core counts, 1MB GMEM, no
> Concurrent Binning & LPAC support. Some of the peripheral blocks like
> RSCC are from A740 that resulted in updates to RSC layout.
>
> Add the necessary devicetree nodes to describe this GPU.
>
> Signed-off-by: Puranam V G Tejaswi <puranam.tejaswi@oss.qualcomm.com>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* [PATCH v4 1/2] dt-bindings: usb: Add ITE IT8851/IT8853 Type-C PD controllers
From: Amber Kao @ 2026-07-17 9:59 UTC (permalink / raw)
To: Jeson Yang, Yaode Fang, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus
Cc: linux-usb, devicetree, linux-kernel, Amber Kao, Bling Chiang,
Eric Su, Doreen Lin
In-Reply-To: <20260717-ucsi-itepd-v4-0-f3ba5addd0df@ite.com.tw>
Add device tree binding for the ITE IT8851 and IT8853 I2C-based USB
Type-C Power Delivery controllers.
The IT8851 supports one Type-C port; the IT8853 is the two-port variant
sharing the same interface.
Add a MAINTAINERS entry for the binding.
Cc: Yaode Fang <Yaode.Fang@ite.com.tw>
Cc: Jeson Yang <jeson.yang@ite.com.tw>
Cc: Bling Chiang <Bling.Chiang@ite.com.tw>
Cc: Eric Su <Eric.Su@ite.com.tw>
Cc: Doreen Lin <doreen.lin@ite.com.tw>
Signed-off-by: Amber Kao <amber.kao@ite.com.tw>
---
.../devicetree/bindings/usb/ite,it8851.yaml | 142 +++++++++++++++++++++
MAINTAINERS | 8 ++
2 files changed, 150 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/ite,it8851.yaml b/Documentation/devicetree/bindings/usb/ite,it8851.yaml
new file mode 100644
index 000000000000..97c1e5490518
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ite,it8851.yaml
@@ -0,0 +1,142 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/ite,it8851.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ITE IT8851/IT8853 USB Type-C Power Delivery Controller
+
+maintainers:
+ - Jeson Yang <jeson.yang@ite.com.tw>
+
+description:
+ The ITE IT8851 is an I2C-based USB Type-C Power Delivery (PD) controller
+ supporting one Type-C port.
+ The IT8853 is the two-port variant sharing the same programming interface.
+
+properties:
+ compatible:
+ enum:
+ - ite,it8851
+ - ite,it8853
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ wakeup-source: true
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+patternProperties:
+ "^connector@[01]$":
+ $ref: /schemas/connector/usb-connector.yaml#
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ite,it8851
+ then:
+ properties:
+ connector@1: false
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ typec@40 {
+ compatible = "ite,it8853";
+ reg = <0x40>;
+ interrupts-extended = <&tlmm 129 IRQ_TYPE_EDGE_FALLING>;
+ wakeup-source;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ label = "USB-C-0";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&eud_con>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&redriver_ss_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ endpoint {
+ remote-endpoint = <&fsa4480_sbu_mux>;
+ };
+ };
+ };
+ };
+
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ label = "USB-C-1";
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&usb1_hs_con>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&redriver1_ss_out>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+ endpoint {
+ remote-endpoint = <&sbu_mux1>;
+ };
+ };
+ };
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 461a3eed6129..ec0eeea79b9e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13720,6 +13720,14 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml
F: drivers/gpu/drm/bridge/ite-it66121.c
+ITE IT8851 TYPE-C PD CONTROLLER DRIVER
+M: Amber Kao <amber.kao@ite.com.tw>
+R: Jeson Yang <jeson.yang@ite.com.tw>
+R: Yaode Fang <Yaode.Fang@ite.com.tw>
+L: linux-usb@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/usb/ite,it8851.yaml
+
IVTV VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net>
L: linux-media@vger.kernel.org
--
2.53.0
^ permalink raw reply related
* [PATCH v4 2/2] usb: typec: ucsi: Add ITE IT8851/IT8853 Type-C PD controller driver
From: Amber Kao @ 2026-07-17 9:59 UTC (permalink / raw)
To: Jeson Yang, Yaode Fang, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus
Cc: linux-usb, devicetree, linux-kernel, Amber Kao, Bling Chiang,
Eric Su, Doreen Lin
In-Reply-To: <20260717-ucsi-itepd-v4-0-f3ba5addd0df@ite.com.tw>
Add a UCSI driver for the ITE IT8851 and IT8853 I2C-based USB Type-C
Power Delivery controllers.
The controller signals UCSI through a shared interrupt line; events are
read and acknowledged via vendor-specific registers, and
UCSI events are forwarded to the UCSI core.
Add the driver file to the MAINTAINERS entry.
Cc: Yaode Fang <Yaode.Fang@ite.com.tw>
Cc: Jeson Yang <jeson.yang@ite.com.tw>
Cc: Bling Chiang <Bling.Chiang@ite.com.tw>
Cc: Eric Su <Eric.Su@ite.com.tw>
Cc: Doreen Lin <doreen.lin@ite.com.tw>
Signed-off-by: Amber Kao <amber.kao@ite.com.tw>
---
MAINTAINERS | 1 +
drivers/usb/typec/ucsi/Kconfig | 10 +
drivers/usb/typec/ucsi/Makefile | 1 +
drivers/usb/typec/ucsi/ucsi_itepd.c | 381 ++++++++++++++++++++++++++++++++++++
4 files changed, 393 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index ec0eeea79b9e..1e76e299e6c3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13727,6 +13727,7 @@ R: Yaode Fang <Yaode.Fang@ite.com.tw>
L: linux-usb@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/usb/ite,it8851.yaml
+F: drivers/usb/typec/ucsi/ucsi_itepd.c
IVTV VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net>
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
index 87dd992a4b9e..0f10dac9b34b 100644
--- a/drivers/usb/typec/ucsi/Kconfig
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -104,4 +104,14 @@ config UCSI_HUAWEI_GAOKUN
To compile the driver as a module, choose M here: the module will be
called ucsi_huawei_gaokun.
+config UCSI_ITEPD
+ tristate "UCSI Interface Driver for ITE IT8851/IT8853"
+ depends on I2C
+ help
+ This driver enables UCSI support on platforms that expose an
+ ITE IT8851/IT8853 Type-C Power Delivery controller over an I2C interface.
+
+ To compile the driver as a module, choose M here: the module
+ will be called ucsi_itepd.
+
endif
diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
index c7e38bf01350..0903a1fd486b 100644
--- a/drivers/usb/typec/ucsi/Makefile
+++ b/drivers/usb/typec/ucsi/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_UCSI_PMIC_GLINK) += ucsi_glink.o
obj-$(CONFIG_CROS_EC_UCSI) += cros_ec_ucsi.o
obj-$(CONFIG_UCSI_LENOVO_YOGA_C630) += ucsi_yoga_c630.o
obj-$(CONFIG_UCSI_HUAWEI_GAOKUN) += ucsi_huawei_gaokun.o
+obj-$(CONFIG_UCSI_ITEPD) += ucsi_itepd.o
diff --git a/drivers/usb/typec/ucsi/ucsi_itepd.c b/drivers/usb/typec/ucsi/ucsi_itepd.c
new file mode 100644
index 000000000000..ceaadb0b3fef
--- /dev/null
+++ b/drivers/usb/typec/ucsi/ucsi_itepd.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026, ITE. All Rights Reserved
+ *
+ */
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/unaligned.h>
+
+#include "ucsi.h"
+
+#define ITEPD_UCSI_VERSION_REG 0x80
+#define ITEPD_UCSI_CCI_REG 0x84
+#define ITEPD_UCSI_MSG_IN_REG 0x88
+#define ITEPD_UCSI_CONTROL_REG 0x98
+
+#define ITEPD_VENDOR_WC_INT 0xbc
+#define ITEPD_VENDOR_INT 0xbd
+#define ITEPD_ALERT_VDM_EVENT BIT(0)
+#define ITEPD_ALERT_UCSI_EVENT BIT(1)
+
+#define ITEPD_MSG_IN_MAX_LEN 0x28
+
+#define ITEPD_EVENT_NONE 0
+#define ITEPD_EVENT_UCSI 1
+#define ITEPD_EVENT_VDM 2
+
+struct itepd {
+ struct i2c_client *client;
+ struct ucsi *ucsi;
+ struct mutex i2c_lock; /* Serializes I2C accesses */
+ struct mutex event_lock; /* Serializes event processing (IRQ vs poll) */
+ struct mutex received_lock; /* Protects cci and msg_in */
+ u8 msg_in[ITEPD_MSG_IN_MAX_LEN];
+ u32 cci;
+};
+
+static u8 ucsi_itepd_get_len(u32 cci)
+{
+ if (cci & UCSI_CCI_COMMAND_COMPLETE)
+ return UCSI_CCI_LENGTH(cci);
+ return 0;
+}
+
+static int itepd_read_reg(struct itepd *itepd, u8 reg, void *data, u32 len)
+{
+ struct i2c_client *client = itepd->client;
+ struct i2c_msg msg[2];
+ u8 *tx_buf, *rx_buf;
+ int ret;
+
+ tx_buf = kzalloc(1, GFP_KERNEL);
+ if (!tx_buf)
+ return -ENOMEM;
+
+ rx_buf = kzalloc(len, GFP_KERNEL);
+ if (!rx_buf) {
+ kfree(tx_buf);
+ return -ENOMEM;
+ }
+
+ tx_buf[0] = reg;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = tx_buf;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = rx_buf;
+
+ mutex_lock(&itepd->i2c_lock);
+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ mutex_unlock(&itepd->i2c_lock);
+ if (ret < 0) {
+ dev_err_ratelimited(&client->dev, "reg 0x%02x read failed: %d\n",
+ reg, ret);
+ goto out_free;
+ }
+ if (ret != ARRAY_SIZE(msg)) {
+ ret = -EIO;
+ goto out_free;
+ }
+
+ memcpy(data, rx_buf, len);
+ ret = 0;
+
+out_free:
+ kfree(rx_buf);
+ kfree(tx_buf);
+ return ret;
+}
+
+static int itepd_write_reg(struct itepd *itepd, u8 reg, const void *data, u32 len)
+{
+ struct i2c_client *client = itepd->client;
+ struct i2c_msg msg[1];
+ u8 *tx_buf;
+ int ret;
+
+ tx_buf = kzalloc(len + 1, GFP_KERNEL);
+ if (!tx_buf)
+ return -ENOMEM;
+
+ tx_buf[0] = reg;
+ memcpy(tx_buf + 1, data, len);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = len + 1;
+ msg[0].buf = tx_buf;
+
+ mutex_lock(&itepd->i2c_lock);
+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ mutex_unlock(&itepd->i2c_lock);
+ if (ret < 0) {
+ dev_err_ratelimited(&client->dev, "reg 0x%02x write failed: %d\n",
+ reg, ret);
+ goto out_free;
+ }
+ if (ret != ARRAY_SIZE(msg)) {
+ ret = -EIO;
+ goto out_free;
+ }
+
+ ret = 0;
+
+out_free:
+ kfree(tx_buf);
+ return ret;
+}
+
+static int itepd_process_event(struct itepd *itepd, u32 *cci)
+{
+ u8 msg_in[ITEPD_MSG_IN_MAX_LEN] = {};
+ __le32 le_cci;
+ u8 event, ack;
+ u8 len = 0;
+ int ret;
+
+ mutex_lock(&itepd->event_lock);
+
+ ret = itepd_read_reg(itepd, ITEPD_VENDOR_INT, &event, sizeof(event));
+ if (ret)
+ goto out_unlock;
+
+ event &= ITEPD_ALERT_VDM_EVENT | ITEPD_ALERT_UCSI_EVENT;
+ if (!event) {
+ mutex_lock(&itepd->received_lock);
+ *cci = itepd->cci;
+ mutex_unlock(&itepd->received_lock);
+ ret = ITEPD_EVENT_NONE;
+ goto out_unlock;
+ }
+
+ if (event & ITEPD_ALERT_UCSI_EVENT) {
+ ret = itepd_read_reg(itepd, ITEPD_UCSI_CCI_REG, &le_cci,
+ sizeof(le_cci));
+ if (ret)
+ goto out_unlock;
+
+ *cci = le32_to_cpu(le_cci);
+ len = min_t(u8, ucsi_itepd_get_len(*cci), sizeof(msg_in));
+ if (len) {
+ ret = itepd_read_reg(itepd, ITEPD_UCSI_MSG_IN_REG,
+ msg_in, len);
+ if (ret)
+ goto out_unlock;
+ }
+ }
+
+ ack = event;
+ ret = itepd_write_reg(itepd, ITEPD_VENDOR_WC_INT, &ack, sizeof(ack));
+ if (ret)
+ goto out_unlock;
+
+ if (event & ITEPD_ALERT_UCSI_EVENT) {
+ mutex_lock(&itepd->received_lock);
+ itepd->cci = *cci;
+ memset(itepd->msg_in, 0, sizeof(itepd->msg_in));
+ memcpy(itepd->msg_in, msg_in, len);
+ mutex_unlock(&itepd->received_lock);
+ ret = ITEPD_EVENT_UCSI;
+ } else {
+ mutex_lock(&itepd->received_lock);
+ *cci = itepd->cci;
+ mutex_unlock(&itepd->received_lock);
+ ret = ITEPD_EVENT_VDM;
+ }
+
+out_unlock:
+ mutex_unlock(&itepd->event_lock);
+ return ret;
+}
+
+static int ucsi_itepd_read_version(struct ucsi *ucsi, u16 *version)
+{
+ struct itepd *itepd = ucsi_get_drvdata(ucsi);
+ __le16 le_version;
+ int ret;
+
+ ret = itepd_read_reg(itepd, ITEPD_UCSI_VERSION_REG, &le_version,
+ sizeof(le_version));
+ if (ret)
+ return ret;
+
+ *version = le16_to_cpu(le_version);
+
+ return 0;
+}
+
+static int ucsi_itepd_read_cci(struct ucsi *ucsi, u32 *cci)
+{
+ struct itepd *itepd = ucsi_get_drvdata(ucsi);
+
+ mutex_lock(&itepd->received_lock);
+ *cci = itepd->cci;
+ mutex_unlock(&itepd->received_lock);
+
+ return 0;
+}
+
+static int ucsi_itepd_poll_cci(struct ucsi *ucsi, u32 *cci)
+{
+ struct itepd *itepd = ucsi_get_drvdata(ucsi);
+ int ret;
+
+ ret = itepd_process_event(itepd, cci);
+ return ret < 0 ? ret : 0;
+}
+
+static int ucsi_itepd_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
+{
+ struct itepd *itepd = ucsi_get_drvdata(ucsi);
+
+ mutex_lock(&itepd->received_lock);
+ memcpy(val, itepd->msg_in, min(val_len, sizeof(itepd->msg_in)));
+ mutex_unlock(&itepd->received_lock);
+
+ return 0;
+}
+
+static int ucsi_itepd_async_control(struct ucsi *ucsi, u64 command)
+{
+ struct itepd *itepd = ucsi_get_drvdata(ucsi);
+ __le64 le_cmd = cpu_to_le64(command);
+
+ if (UCSI_COMMAND(command) == UCSI_PPM_RESET) {
+ mutex_lock(&itepd->received_lock);
+ itepd->cci = 0;
+ mutex_unlock(&itepd->received_lock);
+ }
+
+ return itepd_write_reg(itepd, ITEPD_UCSI_CONTROL_REG, &le_cmd,
+ sizeof(le_cmd));
+}
+
+static const struct ucsi_operations ucsi_itepd_ops = {
+ .read_version = ucsi_itepd_read_version,
+ .read_cci = ucsi_itepd_read_cci,
+ .poll_cci = ucsi_itepd_poll_cci,
+ .read_message_in = ucsi_itepd_read_message_in,
+ .sync_control = ucsi_sync_control_common,
+ .async_control = ucsi_itepd_async_control,
+};
+
+static irqreturn_t itepd_irq_process(struct itepd *itepd)
+{
+ u32 cci;
+ int ret;
+
+ ret = itepd_process_event(itepd, &cci);
+ if (ret < 0 || ret == ITEPD_EVENT_NONE)
+ return IRQ_NONE;
+
+ if (ret == ITEPD_EVENT_UCSI)
+ ucsi_notify_common(itepd->ucsi, cci);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t itepd_irq_thread_fn(int irq, void *data)
+{
+ struct itepd *itepd = data;
+
+ return itepd_irq_process(itepd);
+}
+
+static int itepd_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct itepd *itepd;
+ u32 cci;
+ int ret;
+
+ if (client->irq <= 0)
+ return dev_err_probe(dev, -ENODEV, "no IRQ provided\n");
+
+ itepd = devm_kzalloc(dev, sizeof(*itepd), GFP_KERNEL);
+ if (!itepd)
+ return -ENOMEM;
+
+ itepd->client = client;
+ mutex_init(&itepd->i2c_lock);
+ mutex_init(&itepd->event_lock);
+ mutex_init(&itepd->received_lock);
+ i2c_set_clientdata(client, itepd);
+
+ itepd->ucsi = ucsi_create(dev, &ucsi_itepd_ops);
+ if (IS_ERR(itepd->ucsi))
+ return PTR_ERR(itepd->ucsi);
+
+ ucsi_set_drvdata(itepd->ucsi, itepd);
+
+ ret = request_threaded_irq(client->irq, NULL, itepd_irq_thread_fn,
+ IRQF_ONESHOT, dev_name(dev), itepd);
+ if (ret) {
+ dev_err(dev, "request_threaded_irq failed - %d\n", ret);
+ goto out_ucsi_destroy;
+ }
+
+ itepd_process_event(itepd, &cci);
+
+ ret = ucsi_register(itepd->ucsi);
+ if (ret) {
+ dev_err(dev, "failed to register UCSI: %d\n", ret);
+ goto out_free_irq;
+ }
+
+ return 0;
+
+out_free_irq:
+ free_irq(client->irq, itepd);
+out_ucsi_destroy:
+ ucsi_destroy(itepd->ucsi);
+ return ret;
+}
+
+static void itepd_remove(struct i2c_client *client)
+{
+ struct itepd *itepd = i2c_get_clientdata(client);
+
+ ucsi_unregister(itepd->ucsi);
+ free_irq(client->irq, itepd);
+ ucsi_destroy(itepd->ucsi);
+}
+
+static const struct of_device_id itepd_of_match_table[] = {
+ { .compatible = "ite,it8851" },
+ { .compatible = "ite,it8853" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, itepd_of_match_table);
+
+static const struct i2c_device_id itepd_id_table[] = {
+ { "ucsi_itepd", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, itepd_id_table);
+
+static struct i2c_driver itepd_driver = {
+ .driver = {
+ .name = "ucsi_itepd",
+ .of_match_table = itepd_of_match_table,
+ },
+ .probe = itepd_probe,
+ .remove = itepd_remove,
+ .id_table = itepd_id_table,
+};
+module_i2c_driver(itepd_driver);
+
+MODULE_AUTHOR("Jeson Yang <jeson.yang@ite.com.tw>");
+MODULE_DESCRIPTION("UCSI driver for ITE IT8851 and IT8853 Type-C PD controllers");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH v4 0/2] usb: typec: ucsi: Add ITE IT8851/IT8853 support
From: Amber Kao @ 2026-07-17 9:59 UTC (permalink / raw)
To: Jeson Yang, Yaode Fang, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus
Cc: linux-usb, devicetree, linux-kernel, Amber Kao, Bling Chiang,
Eric Su, Doreen Lin
This series adds Device Tree bindings and minimal UCSI driver support
for the ITE IT8851/IT8853 USB Type-C Power Delivery controller over I2C.
Changes in v4:
- Use separate tx/rx buffers in itepd_read_reg() for DMA safety
- Rate-limit error prints in the I2C accessors
- Refactor IRQ and poll_cci() into a common itepd_process_event()
helper serialized by event_lock; poll_cci() now acks events
- Clear cached CCI on PPM_RESET
- Drain pending events in probe instead of a manual interrupt-clear
- Keep ucsi_unregister() before free_irq() in remove(): the IRQ
handler is the only event consumer/acker on this device, so
freeing the IRQ first stalls in-flight commands until timeout and
leaves the PPM with an unacked event. ucsi_unregister() disables
notifications before freeing connectors, closing the reported UAF
window in practice. Matches other UCSI I2C drivers.
- Use device-specific compatibles "ite,it8851"/"ite,it8853"
- Move version changelog below the "---" line (Krzysztof)
- Trim MAINTAINERS reviewer list (Krzysztof)
Link to v3: https://lore.kernel.org/all/20260710-ucsi-itepd-feature-v3-0-8523e1e1c47a@ite.com.tw/
Link to v2: https://lore.kernel.org/all/20260710-ucsi-itepd-feature-v2-0-41943fd5df38@ite.com.tw/
Link to v1: https://lore.kernel.org/all/20260615-ucsi-itepd-feature-v1-0-a826cfd0df6a@ite.com.tw/
Signed-off-by: Amber Kao <amber.kao@ite.com.tw>
---
Amber Kao (2):
dt-bindings: usb: Add ITE IT8851/IT8853 Type-C PD controllers
usb: typec: ucsi: Add ITE IT8851/IT8853 Type-C PD controller driver
.../devicetree/bindings/usb/ite,it8851.yaml | 142 ++++++++
MAINTAINERS | 9 +
drivers/usb/typec/ucsi/Kconfig | 10 +
drivers/usb/typec/ucsi/Makefile | 1 +
drivers/usb/typec/ucsi/ucsi_itepd.c | 381 +++++++++++++++++++++
5 files changed, 543 insertions(+)
---
base-commit: 8fde5d1d47f69db6082dfa34500c27f8485389a5
change-id: 20260717-ucsi-itepd-4e943e1382f0
Best regards,
--
Amber Kao <amber.kao@ite.com.tw>
^ permalink raw reply
* Re: [RFC PATCH 1/9] dt-bindings: npu: rockchip: add rockchip,rk3576-rknn-core
From: Chaoyi Chen @ 2026-07-17 10:02 UTC (permalink / raw)
To: Jiaxing Hu, tomeu, heiko, robh, krzk+dt, conor+dt, joro, will,
robin.murphy, ulfh, p.zabel, ogabbay
Cc: dri-devel, linux-rockchip, iommu, linux-pm, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260717085220.3212274-2-gahing@gahingwoo.com>
Hello Jiaxing,
On 7/17/2026 4:50 PM, Jiaxing Hu wrote:
> Document the RK3576 NPU core: add rockchip,rk3576-rknn-core to the
> compatible enum and drop sram-supply from required (RK3576 has no NPU
> SRAM supply).
>
> Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>
> ---
> .../devicetree/bindings/npu/rockchip,rk3588-rknn-core.yaml | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/npu/rockchip,rk3588-rknn-core.yaml b/Documentation/devicetree/bindings/npu/rockchip,rk3588-rknn-core.yaml
> index caca2a490..d904db3bf 100644
> --- a/Documentation/devicetree/bindings/npu/rockchip,rk3588-rknn-core.yaml
> +++ b/Documentation/devicetree/bindings/npu/rockchip,rk3588-rknn-core.yaml
> @@ -21,6 +21,7 @@ properties:
>
> compatible:
> enum:
> + - rockchip,rk3576-rknn-core
> - rockchip,rk3588-rknn-core
>
> reg:
> @@ -75,7 +76,6 @@ required:
> - resets
> - reset-names
> - npu-supply
> - - sram-supply
>
You should not delete this item directly. Instead, use the compatible
to distinguish whether it is required.
> additionalProperties: false
>
--
Best,
Chaoyi
^ permalink raw reply
* Re: [PATCH 0/2] qcom_battmgr: Add batteryless DC-adapter MAINS support
From: Rakesh Kota @ 2026-07-17 10:00 UTC (permalink / raw)
To: Bjorn Andersson
Cc: Krzysztof Kozlowski, Konrad Dybcio, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sebastian Reichel,
linux-arm-msm, devicetree, linux-kernel, linux-pm, jishnu.prakash,
kamal.wadhwa
In-Reply-To: <alltBcYWULOv7nEv@baldur>
On Thu, Jul 16, 2026 at 06:54:36PM -0500, Bjorn Andersson wrote:
> On Thu, Jul 16, 2026 at 02:18:50PM +0530, Rakesh Kota wrote:
> > On Fri, Jul 03, 2026 at 11:16:59AM +0200, Krzysztof Kozlowski wrote:
> > > On 03/07/2026 11:13, Rakesh Kota wrote:
> > > > On Thu, Jul 02, 2026 at 01:28:35PM +0200, Krzysztof Kozlowski wrote:
> > > >> On 02/07/2026 13:17, Rakesh Kota wrote:
> > > >>> On Tue, Jun 30, 2026 at 04:16:13PM +0200, Konrad Dybcio wrote:
> > > >>>> On 5/22/26 12:56 AM, Bjorn Andersson wrote:
> > > >>>>> On Tue, May 19, 2026 at 12:29:38PM +0530, Rakesh Kota wrote:
> > > >>>>>> On Mon, May 18, 2026 at 04:36:32PM +0200, Konrad Dybcio wrote:
> > > >>>>>>> On 5/18/26 3:49 PM, Rakesh Kota wrote:
> > > >>>>>>>> On batteryless boards powered by 12V DC adapters, registering the
> > > >>>>>>>> power supply as BATTERY causes userspace to incorrectly trigger
> > > >>>>>>>> battery power-saving sequences.
> > > >>>>>>>
> > > >>>>>>> Does battman really offer no way of differentiating whether a battery
> > > >>>>>>> is *actually* present in such cases?
> > > >>>>>>>
> > > >>>>>>> What boards are affected?
> > > >>>>>>>
> > > >>>>>> Currently, batteryless support is only implemented for the
> > > >>>>>> qcs6490-rb3gen2(Kodiak) board.
> > > >>>>>>
> > > >>>>>
> > > >>>>> What do you mean?
> > > >>>>>
> > > >>>>> Are you saying that the pmic_glink firmware in Kodiak has a one-off hack
> > > >>>>> that no other implementation of this firmware has?
> > > >>>>>
> > > >>>>> My Lenovo IdeaCentre (hamoa) doesn't have battery, what should I do now?
> > > >>>>
> > > >>>> I was going through my inbox.
> > > >>>> This remains unanswered, and I don't see the discussion progressing
> > > >>>> without resolving this.
> > > >>>>
> > > >>> To clarify — there is no platform-side hack involved. The Kodiak board
> > > >>> has a batteryless variant, but the pmic_glink firmware provides no way
> > > >>> to distinguish whether a battery is physically present or not. Since
> > > >>> this can't be determined from firmware, we introduced a DT-based
> > > >>> property to describe the hardware configuration explicitly.
> > > >>>
> > > >>> This is not Kodiak-specific — any batteryless board, including hamoa,
> > > >>> can use the same DT property to avoid incorrect BATTERY registration
> > > >>
> > > >> Unfortunately the answer might be: fix your firmware. Since your
> > > >> firmware is the interface and we do not expose battery in DT, then you
> > > >> do not get additional properties. You made conscious design choice of
> > > >> abstracting some things in the firmware, so you do control that part of
> > > >> the software stack. If you make one choice, it might lead to other, like
> > > >> rejecting such properties.
> > > >>
> > > >
> > > > This is a hardware limitation — both the debug board and batteryless
> > > > platform use the same Batt_ID resistor (10K), so the firmware has no way
> > > > to distinguish between the two at runtime. There is nothing to fix on
> > > > the firmware side.
> > > >
> > > > Given this, would a new compatible string (e.g.,qcom,pmic-glink-batteryless)
> > > > be preferred over a DT property, or do you have another suggestion?
> > >
> > > Debug board is not a end device, thus you basically have only one real
> > > use case: battery less. Treat everything that.
> >
> >
> > can we have 2 supplies added - (fake) battery and mains? if we detect 10K bat id?
> > since mobile/production platforms share the same firmware and driver code,
> > the debug board still requires a fake battery registration to keep the common
> > code path functional. In that scenario, should we register both the main power
> > supply (DC adapter) and a fake battery, so the shared code continues to work
> > correctly without requiring platform-specific divergence?
> >
>
> My Hamoa-based PC (desktop) currently reports: ac, battery, usb, and
> wireless. I would expect that it reports on AC (or no battmgr
> interfaces?).
>
> If I understand what you're saying, the pmic-glink firmware is generic
> across all Hamoa targets, so there is no configuration in that firmware
> to differentiate between this and a laptop usecase?
>
> Similarly, my Hamoa laptop doesn't have wireless charging, but you're
> saying the pmic-glink firmware doesn't know about this - it just don't
> get any input power on those pins?
>
>
> I think this is similar to if we had a discrete charger block that we
> describe in DeviceTree, we would somehow have to describe the
> "configuration" of that component.
>
> But I don't think you considered those other use cases. Perhaps this
> should be an optional qcom,battmgr-interfaces = "ac", "usb" ...; taking
> the list of interfaces that is actually implemented.
>
Thank you for the suggestion, Bjorn!
Yes, qcom,battmgr-interfaces = "ac", "usb"; sounds like the right
approach — it cleanly covers all use cases.
@Krzysztof Kozlowski, could you please share your thoughts on this direction? Would
you be okay with adding this as an optional DT property?
regards
Rakesh Kota
> Regards,
> Bjorn
>
^ permalink raw reply
* Re: [PATCH 6/8] arm64: dts: qcom: eliza: Add GPU SMMU node
From: Konrad Dybcio @ 2026-07-17 9:59 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Puranam V G Tejaswi, Abel Vesa, linux-arm-msm, dri-devel,
freedreno, linux-kernel, devicetree, linux-arm-kernel, iommu,
Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Will Deacon, Robin Murphy, Joerg Roedel (AMD)
In-Reply-To: <e8255fe2-a67c-490e-a905-ed056c6af950@oss.qualcomm.com>
On 7/13/26 9:47 PM, Akhil P Oommen wrote:
> On 7/6/2026 4:38 PM, Konrad Dybcio wrote:
>> On 7/6/26 1:07 PM, Konrad Dybcio wrote:
>>> On 7/5/26 10:14 AM, Akhil P Oommen wrote:
>>>> From: Abel Vesa <abel.vesa@oss.qualcomm.com>
>>>>
>>>> Add the nodes to describe the GPU SMMU.
>>>>
>>>> Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
>>>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>>>> ---
>>>> arch/arm64/boot/dts/qcom/eliza.dtsi | 38 +++++++++++++++++++++++++++++++++++++
>>>> 1 file changed, 38 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/qcom/eliza.dtsi b/arch/arm64/boot/dts/qcom/eliza.dtsi
>>>> index c5635f22e2a7..e5b8377e6c3a 100644
>>>> --- a/arch/arm64/boot/dts/qcom/eliza.dtsi
>>>> +++ b/arch/arm64/boot/dts/qcom/eliza.dtsi
>>>> @@ -2674,6 +2674,44 @@ mdss_dp0_out: endpoint {
>>>> };
>>>> };
>>>>
>>>> + adreno_smmu: iommu@3da0000 {
>>>> + compatible = "qcom,eliza-smmu-500", "qcom,adreno-smmu",
>>>> + "qcom,smmu-500", "arm,mmu-500";
>>>> + reg = <0x0 0x03da0000 0x0 0x40000>;
>>>> + #iommu-cells = <2>;
>>>> + #global-interrupts = <1>;
>>>> + interrupts = <GIC_SPI 673 IRQ_TYPE_LEVEL_HIGH>,
>>>
>>> 674 is the correct globla
>>
>> (modulo the issue i explained below)
>>
>> [...]
>>
>>> This list is not quite correct. It must be sorted by the context index,
>>> to which a given interrupt corresponds to - the driver relies on that
>>> to give you information about where a context fault happens
>>>
>>> Moreover, I see that the interrupt sheet has the bug where some
>>> interrupts are offset by 32 from the base vector, and others are offset
>>> by 31 (i.e. the SPI number doesn't equal irq vector - 32) - please find
>>> out which mapping is correct with the right folks
>
> I reviewed this and looks correct to me. Also, this matches the
> downstream configuration. Did you confuse with Dest Port vs Vector ID in
> the documentation?
What I'm trying to say is that the documentation is confusing, we've had
that issue in the past on other platforms. If you see that the correct
irqs are firing, it's fine
Konrad
^ permalink raw reply
* [PATCH v2 3/3] arm64: dts: qcom: monaco: enable audio ML offload memory and SMMU mappings
From: Pratyush Meduri @ 2026-07-17 9:58 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Manivannan Sadhasivam
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel
In-Reply-To: <20260717095825.3962666-1-pratyush.meduri@oss.qualcomm.com>
The audio ML (machine-learning) offload use case requires a contiguous,
physically addressable buffer shared with the audio DSP/SPF, and issues
DMA transactions through additional SMMU stream IDs that are not
covered by the existing ADSP mapping.
Add a dedicated reusable shared-dma-pool CMA region (16 MiB, 4 MiB
aligned) and wire it to the q6apm DAIs node via memory-region. A
dedicated pool guarantees the alignment and contiguity the DSP expects
and isolates these allocations from the default CMA region.
Under the EL2 (Gunyah/hypervisor) configuration the SMMU is fully
enforcing, so the ML transactions are otherwise blocked and faulted:
arm-smmu 15000000.iommu: Blocked unknown Stream ID 0x2060
arm-smmu 15000000.iommu: Blocked unknown Stream ID 0x2062
Add the ML-related stream IDs (0x3060 mask 0x9, 0x3062 mask 0x1) to the
remoteproc_adsp iommus property in the EL2 overlay so these buffers are
translated by the SMMU instead of being rejected.
Signed-off-by: Pratyush Meduri <pratyush.meduri@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/monaco-el2.dtso | 4 +++-
arch/arm64/boot/dts/qcom/monaco.dtsi | 9 +++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/monaco-el2.dtso b/arch/arm64/boot/dts/qcom/monaco-el2.dtso
index a7e3270f8609..97bb8287cec3 100644
--- a/arch/arm64/boot/dts/qcom/monaco-el2.dtso
+++ b/arch/arm64/boot/dts/qcom/monaco-el2.dtso
@@ -17,7 +17,9 @@ &iris {
};
&remoteproc_adsp {
- iommus = <&apps_smmu 0x2000 0x0>;
+ iommus = <&apps_smmu 0x2000 0x0>,
+ <&apps_smmu 0x2060 0x9>,
+ <&apps_smmu 0x2062 0x1>;
};
&remoteproc_cdsp {
diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
index 64fc0d592282..d971c0ea1b30 100644
--- a/arch/arm64/boot/dts/qcom/monaco.dtsi
+++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
@@ -729,6 +729,14 @@ reserved-memory {
#size-cells = <2>;
ranges;
+ audio_cma_mem: qcom,audio-ml {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
+ reusable;
+ alignment = <0x0 0x400000>;
+ size = <0x0 0x1000000>;
+ };
+
aop_image_mem: aop-image-region@90800000 {
reg = <0x0 0x90800000 0x0 0x60000>;
no-map;
@@ -2844,6 +2852,7 @@ q6apmbedai: bedais {
q6apmdai: dais {
compatible = "qcom,q6apm-dais";
iommus = <&apps_smmu 0x2001 0x0>;
+ memory-region = <&audio_cma_mem>;
};
};
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/3] arm64: dts: qcom: lemans: enable audio ML offload memory and SMMU mappings
From: Pratyush Meduri @ 2026-07-17 9:58 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Manivannan Sadhasivam
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel
In-Reply-To: <20260717095825.3962666-1-pratyush.meduri@oss.qualcomm.com>
The audio ML (machine-learning) offload use case requires a contiguous,
physically addressable buffer shared with the audio DSP/SPF, and issues
DMA transactions through additional SMMU stream IDs that are not
covered by the existing ADSP mapping.
Add a dedicated reusable shared-dma-pool CMA region (16 MiB, 4 MiB
aligned) and wire it to the q6apm DAIs node via memory-region. A
dedicated pool guarantees the alignment and contiguity the DSP expects
and isolates these allocations from the default CMA region.
Under the EL2 (Gunyah/hypervisor) configuration the SMMU is fully
enforcing, so the ML transactions are otherwise blocked and faulted:
arm-smmu 15000000.iommu: Blocked unknown Stream ID 0x3060
arm-smmu 15000000.iommu: Blocked unknown Stream ID 0x3062
Add the ML-related stream IDs (0x3060 mask 0x9, 0x3062 mask 0x1) to the
remoteproc_adsp iommus property in the EL2 overlay so these buffers are
translated by the SMMU instead of being rejected.
Signed-off-by: Pratyush Meduri <pratyush.meduri@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/lemans-el2.dtso | 4 +++-
arch/arm64/boot/dts/qcom/lemans.dtsi | 9 +++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/lemans-el2.dtso b/arch/arm64/boot/dts/qcom/lemans-el2.dtso
index 621ad930cf54..5b477346ef90 100644
--- a/arch/arm64/boot/dts/qcom/lemans-el2.dtso
+++ b/arch/arm64/boot/dts/qcom/lemans-el2.dtso
@@ -19,7 +19,9 @@ &iris {
};
&remoteproc_adsp {
- iommus = <&apps_smmu 0x3000 0x0>;
+ iommus = <&apps_smmu 0x3000 0x0>,
+ <&apps_smmu 0x3060 0x9>,
+ <&apps_smmu 0x3062 0x1>;
};
&remoteproc_cdsp0 {
diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi
index 3b0539e27b51..060565113784 100644
--- a/arch/arm64/boot/dts/qcom/lemans.dtsi
+++ b/arch/arm64/boot/dts/qcom/lemans.dtsi
@@ -624,6 +624,14 @@ reserved-memory {
#size-cells = <2>;
ranges;
+ audio_cma_mem: qcom,audio-ml {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
+ reusable;
+ alignment = <0x0 0x400000>;
+ size = <0x0 0x1000000>;
+ };
+
sail_ss_mem: sail-ss@80000000 {
reg = <0x0 0x80000000 0x0 0x10000000>;
no-map;
@@ -8134,6 +8142,7 @@ q6apmbedai: bedais {
q6apmdai: dais {
compatible = "qcom,q6apm-dais";
iommus = <&apps_smmu 0x3001 0x0>;
+ memory-region = <&audio_cma_mem>;
};
};
--
2.34.1
^ permalink raw reply related
* [PATCH v5 3/3] arm64: dts: qcom: glymur: Wire PCIe3a/3b to shared Gen5x8 PHY
From: Qiang Yu @ 2026-07-17 9:58 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Manivannan Sadhasivam, Philipp Zabel,
Bjorn Andersson, Konrad Dybcio
Cc: Qiang Yu, linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <20260717-glymur_linkmode_0717-v5-0-4f9e87a61463@oss.qualcomm.com>
Glymur's PCIe3a and PCIe3b controllers share a single Gen5x8 QMP PHY block
that can be bifurcated into two independent x4 links, rather than each
controller owning its own dedicated PHY.
Add a pcie3_phy node describing the shared PHY block, add the missing
PCIe3a controller node, and point both PCIe3a's and PCIe3b's port phys
at &pcie3_phy (index 0 and 1 respectively) so each controller picks up
its half of the bifurcated PHY. Update the GCC pipe clock parent array
to reference the new PHY's clock outputs instead of the placeholders.
Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/glymur-crd.dtsi | 8 +
arch/arm64/boot/dts/qcom/glymur.dtsi | 336 ++++++++++++++++++++++++++++++-
2 files changed, 342 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi
index c12808abbfe1..e8e81bf9a6a1 100644
--- a/arch/arm64/boot/dts/qcom/glymur-crd.dtsi
+++ b/arch/arm64/boot/dts/qcom/glymur-crd.dtsi
@@ -750,6 +750,14 @@ &pcie3b {
pinctrl-names = "default";
};
+&pcie3_phy {
+ vdda-phy-supply = <&vreg_l3c_e1_0p89>;
+ vdda-pll-supply = <&vreg_l2c_e1_1p14>;
+
+ vdda-refgen0p9-supply = <&vreg_l1c_e1_0p82>;
+ vdda-refgen1p2-supply = <&vreg_l4f_e1_1p08>;
+};
+
&pcie3b_port0 {
reset-gpios = <&tlmm 155 GPIO_ACTIVE_LOW>;
wake-gpios = <&tlmm 157 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm64/boot/dts/qcom/glymur.dtsi b/arch/arm64/boot/dts/qcom/glymur.dtsi
index 6d058d591039..edd09b84b8b9 100644
--- a/arch/arm64/boot/dts/qcom/glymur.dtsi
+++ b/arch/arm64/boot/dts/qcom/glymur.dtsi
@@ -801,8 +801,8 @@ gcc: clock-controller@100000 {
<0>, /* USB 2 Phy PCIE PIPEGMUX */
<0>, /* USB 2 Phy PIPEGMUX */
<0>, /* USB 2 Phy SYS PCIE PIPEGMUX */
- <0>, /* PCIe 3a */
- <0>, /* PCIe 3b */
+ <&pcie3_phy 0>, /* PCIe 3a pipe */
+ <&pcie3_phy 1>, /* PCIe 3b pipe */
<&pcie4_phy>, /* PCIe 4 */
<&pcie5_phy>, /* PCIe 5 */
<&pcie6_phy>, /* PCIe 6 */
@@ -2329,6 +2329,62 @@ &config_noc SLAVE_QUP_0 QCOM_ICC_TAG_ALWAYS>,
};
};
+ pcie3_phy: phy@f00000 {
+ compatible = "qcom,glymur-qmp-gen5x8-pcie-phy";
+ reg = <0x0 0x00f00000 0x0 0x10000>,
+ <0x0 0x00f10000 0x0 0x10000>;
+ reg-names = "port_a",
+ "port_b";
+
+ clocks = <&gcc GCC_PCIE_PHY_3A_AUX_CLK>,
+ <&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
+ <&tcsr TCSR_PCIE_3_CLKREF_EN>,
+ <&gcc GCC_PCIE_3A_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_3A_PIPE_CLK>,
+ <&gcc GCC_PCIE_PHY_3B_AUX_CLK>,
+ <&gcc GCC_PCIE_3B_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_3B_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_3B_PIPE_CLK>,
+ <&gcc GCC_PCIE_3B_PIPE_DIV2_CLK>;
+ clock-names = "aux",
+ "cfg_ahb",
+ "ref",
+ "rchng",
+ "pipe",
+ "phy_b_aux",
+ "cfg_ahb_b",
+ "rchng_b",
+ "pipe_b",
+ "pipediv2_b";
+
+ resets = <&gcc GCC_PCIE_3A_PHY_BCR>,
+ <&gcc GCC_PCIE_3A_NOCSR_COM_PHY_BCR>,
+ <&gcc GCC_PCIE_3B_PHY_BCR>,
+ <&gcc GCC_PCIE_3B_NOCSR_COM_PHY_BCR>;
+ reset-names = "phy_a",
+ "phy_a_nocsr",
+ "phy_b",
+ "phy_b_nocsr";
+
+ assigned-clocks = <&gcc GCC_PCIE_3A_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_3B_PHY_RCHNG_CLK>;
+ assigned-clock-rates = <100000000>, <100000000>;
+
+ power-domains = <&gcc GCC_PCIE_3A_PHY_GDSC>,
+ <&gcc GCC_PCIE_3B_PHY_GDSC>;
+ power-domain-names = "phy_a_gdsc", "phy_b_gdsc";
+
+ qcom,link-mode = <&tcsr 0x5000>;
+
+ #clock-cells = <1>;
+ clock-output-names = "pcie3a_pipe_clk",
+ "pcie3b_pipe_clk";
+
+ #phy-cells = <1>;
+
+ status = "disabled";
+ };
+
usb_hs_phy: phy@fa0000 {
compatible = "qcom,glymur-m31-eusb2-phy",
"qcom,sm8750-m31-eusb2-phy";
@@ -3691,6 +3747,282 @@ pcie3b_port0: pcie@0 {
reg = <0x0 0x0 0x0 0x0 0x0>;
bus-range = <0x01 0xff>;
+ phys = <&pcie3_phy 1>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+ };
+
+ pcie3a: pci@1c10000 {
+ device_type = "pci";
+ compatible = "qcom,glymur-pcie", "qcom,pcie-x1e80100";
+ reg = <0x0 0x01c10000 0x0 0x3000>,
+ <0x0 0x70000000 0x0 0xf20>,
+ <0x0 0x70000f40 0x0 0xa8>,
+ <0x0 0x70001000 0x0 0x4000>,
+ <0x0 0x70100000 0x0 0x100000>,
+ <0x0 0x01c13000 0x0 0x1000>;
+ reg-names = "parf",
+ "dbi",
+ "elbi",
+ "atu",
+ "config",
+ "mhi";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x00000000 0x0 0x70200000 0x0 0x100000>,
+ <0x02000000 0x0 0x70000000 0x0 0x70300000 0x0 0x3d00000>,
+ <0x03000000 0x7 0x00000000 0x7 0x00000000 0x0 0x40000000>,
+ <0x43000000 0x70 0x00000000 0x70 0x00000000 0x10 0x00000000>;
+
+ bus-range = <0 0xff>;
+
+ dma-coherent;
+
+ linux,pci-domain = <3>;
+ num-lanes = <8>;
+
+ operating-points-v2 = <&pcie3a_opp_table>;
+
+ msi-map = <0x0 &gic_its 0xb0000 0x10000>;
+ iommu-map = <0x0 &pcie_smmu 0x30000 0x10000>;
+
+ interrupts = <GIC_SPI 948 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 949 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 844 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 845 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 846 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 847 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 942 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0",
+ "msi1",
+ "msi2",
+ "msi3",
+ "msi4",
+ "msi5",
+ "msi6",
+ "msi7",
+ "global";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 0 848 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 0 849 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 0 850 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 0 851 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_PCIE_3A_AUX_CLK>,
+ <&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_3A_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_3A_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_3A_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_3A_WEST_SF_AXI_CLK>;
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "noc_aggr";
+
+ assigned-clocks = <&gcc GCC_PCIE_3A_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ interconnects = <&pcie_west_anoc MASTER_PCIE_3A QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+ <&hsc_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
+ &pcie_west_slv_noc SLAVE_PCIE_3A QCOM_ICC_TAG_ALWAYS>;
+ interconnect-names = "pcie-mem",
+ "cpu-pcie";
+
+ resets = <&gcc GCC_PCIE_3A_BCR>,
+ <&gcc GCC_PCIE_3A_LINK_DOWN_BCR>;
+ reset-names = "pci",
+ "link_down";
+
+ power-domains = <&gcc GCC_PCIE_3A_GDSC>;
+
+ eq-presets-8gts = /bits/ 16 <0x5555 0x5555 0x5555 0x5555
+ 0x5555 0x5555 0x5555 0x5555>;
+ eq-presets-16gts = /bits/ 8 <0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55>;
+ eq-presets-32gts = /bits/ 8 <0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55>;
+
+ status = "disabled";
+
+ pcie3a_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ /* GEN 1 x1 */
+ opp-2500000-1 {
+ opp-hz = /bits/ 64 <2500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <250000 1>;
+ opp-level = <1>;
+ };
+
+ /* GEN 1 x2 */
+ opp-5000000-1 {
+ opp-hz = /bits/ 64 <5000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <500000 1>;
+ opp-level = <1>;
+ };
+
+ /* GEN 1 x4 */
+ opp-10000000-1 {
+ opp-hz = /bits/ 64 <10000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <1000000 1>;
+ opp-level = <1>;
+ };
+
+ /* GEN 1 x8 */
+ opp-20000000-1 {
+ opp-hz = /bits/ 64 <20000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <2000000 1>;
+ opp-level = <1>;
+ };
+
+ /* GEN 2 x1 */
+ opp-5000000-2 {
+ opp-hz = /bits/ 64 <5000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <500000 1>;
+ opp-level = <2>;
+ };
+
+ /* GEN 2 x2 */
+ opp-10000000-2 {
+ opp-hz = /bits/ 64 <10000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <1000000 1>;
+ opp-level = <2>;
+ };
+
+ /* GEN 2 x4 */
+ opp-20000000-2 {
+ opp-hz = /bits/ 64 <20000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <2000000 1>;
+ opp-level = <2>;
+ };
+
+ /* GEN 2 x8 */
+ opp-40000000-2 {
+ opp-hz = /bits/ 64 <40000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <4000000 1>;
+ opp-level = <2>;
+ };
+
+ /* GEN 3 x1 */
+ opp-8000000-3 {
+ opp-hz = /bits/ 64 <8000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <984500 1>;
+ opp-level = <3>;
+ };
+
+ /* GEN 3 x2 */
+ opp-16000000-3 {
+ opp-hz = /bits/ 64 <16000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <1969000 1>;
+ opp-level = <3>;
+ };
+
+ /* GEN 3 x4 */
+ opp-32000000-3 {
+ opp-hz = /bits/ 64 <32000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <3938000 1>;
+ opp-level = <3>;
+ };
+
+ /* GEN 3 x8 */
+ opp-64000000-3 {
+ opp-hz = /bits/ 64 <64000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ opp-peak-kBps = <7876000 1>;
+ opp-level = <3>;
+ };
+
+ /* GEN 4 x1 */
+ opp-16000000-4 {
+ opp-hz = /bits/ 64 <16000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ opp-peak-kBps = <1969000 1>;
+ opp-level = <4>;
+ };
+
+ /* GEN 4 x2 */
+ opp-32000000-4 {
+ opp-hz = /bits/ 64 <32000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ opp-peak-kBps = <3938000 1>;
+ opp-level = <4>;
+ };
+
+ /* GEN 4 x4 */
+ opp-64000000-4 {
+ opp-hz = /bits/ 64 <64000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ opp-peak-kBps = <7876000 1>;
+ opp-level = <4>;
+ };
+
+ /* GEN 4 x8 */
+ opp-128000000-4 {
+ opp-hz = /bits/ 64 <128000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ opp-peak-kBps = <15753000 1>;
+ opp-level = <4>;
+ };
+
+ /* GEN 5 x1 */
+ opp-32000000-5 {
+ opp-hz = /bits/ 64 <32000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <3938000 1>;
+ opp-level = <5>;
+ };
+
+ /* GEN 5 x2 */
+ opp-64000000-5 {
+ opp-hz = /bits/ 64 <64000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <7876000 1>;
+ opp-level = <5>;
+ };
+
+ /* GEN 5 x4 */
+ opp-128000000-5 {
+ opp-hz = /bits/ 64 <128000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <15753000 1>;
+ opp-level = <5>;
+ };
+
+ /* GEN 5 x8 */
+ opp-256000000-5 {
+ opp-hz = /bits/ 64 <256000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ opp-peak-kBps = <31506000 1>;
+ opp-level = <5>;
+ };
+ };
+
+ pcie3a_port0: pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ bus-range = <0x01 0xff>;
+
+ phys = <&pcie3_phy 0>;
+
#address-cells = <3>;
#size-cells = <2>;
ranges;
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/3] dt-bindings: remoteproc: qcom,pas-common: allow up to 3 iommus
From: Pratyush Meduri @ 2026-07-17 9:58 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Manivannan Sadhasivam
Cc: linux-arm-msm, linux-remoteproc, devicetree, linux-kernel
In-Reply-To: <20260717095825.3962666-1-pratyush.meduri@oss.qualcomm.com>
The ADSP PAS on several Qualcomm SoCs (e.g. SA8775P/lemans, QCS8300,
Monaco) needs more than a single SMMU stream ID for the audio ML
(machine-learning) offload use case. In addition to the primary
ADSP stream ID, the DSP/SPF issues DMA transactions through extra
stream IDs that are not covered by the existing single-entry mapping.
Relax the iommus constraint to allow between 1 and 3 entries so the
additional ML offload stream IDs can be described, fixing dtb_check
schema violations on device trees that add them.
Signed-off-by: Pratyush Meduri <pratyush.meduri@oss.qualcomm.com>
---
.../devicetree/bindings/remoteproc/qcom,pas-common.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
index 11faf655f530..fb656bda8527 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml
@@ -33,7 +33,8 @@ properties:
maxItems: 6
iommus:
- maxItems: 1
+ minItems: 1
+ maxItems: 3
power-domains:
minItems: 1
--
2.34.1
^ permalink raw reply related
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