Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] dt-bindings: net: dsa: nxp,sja1105: make spi-cpol optional for sja1110
From: Josua Mayer @ 2026-04-09 12:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer
In-Reply-To: <20260409-imx8dxl-sr-som-v2-0-83ff20629ba0@solid-run.com>

Currently, the binding requires 'spi-cpha' for SJA1105 and 'spi-cpol'
for SJA1110.

However, the SJA1110 supports both SPI modes 0 and 2. Mode 2
(cpha=0, cpol=1) is used by the NXP LX2160 Bluebox 3.

On the SolidRun i.MX8DXL HummingBoard Telematics, mode 0 is stable,
while forcing mode 2 introduces CRC errors especially during bursts.

Drop the requirement on spi-cpol for SJA1110.

Fixes: af2eab1a8243 ("dt-bindings: net: nxp,sja1105: document spi-cpol/cpha")
Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
index 607b7fe8d28ee..0486489114cd8 100644
--- a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
@@ -143,8 +143,6 @@ allOf:
     else:
       properties:
         spi-cpha: false
-      required:
-        - spi-cpol
 
 unevaluatedProperties: false
 

-- 
2.51.0



^ permalink raw reply related

* [PATCH v2 2/3] dt-bindings: arm: fsl: Add SolidRun i.MX8DXL SoM and HummingBoard
From: Josua Mayer @ 2026-04-09 12:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer,
	Krzysztof Kozlowski
In-Reply-To: <20260409-imx8dxl-sr-som-v2-0-83ff20629ba0@solid-run.com>

Add binding for the SolidRun i.MX8DXL based System on Module, and the
reference HummingBoard Telematics.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 5716d701292cf..c7a885159318f 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -1376,6 +1376,13 @@ properties:
               - fsl,imx8dxl-evk           # i.MX8DXL EVK Board
           - const: fsl,imx8dxl
 
+      - description: SolidRun i.MX8DXL SoM based boards
+        items:
+          - enum:
+              - solidrun,imx8dxl-hummingboard-telematics # SolidRun i.MX8DXL SoM EVK Board
+          - const: solidrun,imx8dxl-sr-som
+          - const: fsl,imx8dxl
+
       - description: i.MX8QXP/i.MX8DX Boards with Toradex Colibri iMX8X Modules
         items:
           - enum:

-- 
2.51.0



^ permalink raw reply related

* [PATCH v2 0/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-09 12:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer,
	Krzysztof Kozlowski

Add bindings and description for SolidRUn i.MX8DXL based SoM and
HummingBoard Telematics.

Modify SJA1110 Ethernet Switch bindings to allow SPI Mode 0.

This patch-set is based on v7.0-rc2, because rc1 was experiencing
deadlocks with imx8qxp clock driver.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
Changes in v2:
- Dropped accidental change to unrelated imx8mp-sr-som.dtsi file.
- Fixed phy-mode on fixed link between cpu and ethernet switch.
  (Reported-by: Andrew Lunn <andrew@lunn.ch>)
- Removed spi-cpol property from ethernet-switch on spi bus, fixing
  sja1110a driver probe.
- Changed SJA1110 bindings to allow removing spi-cpol property.
- Aligned comments on all ethernet switch port nodes to be consistent.
- Dropped regulator-always-on from dsrc radio power-supplies.
- Link to v1: https://lore.kernel.org/r/20260408-imx8dxl-sr-som-v1-0-ce5a39acd713@solid-run.com

---
Josua Mayer (3):
      dt-bindings: net: dsa: nxp,sja1105: make spi-cpol optional for sja1110
      dt-bindings: arm: fsl: Add SolidRun i.MX8DXL SoM and HummingBoard
      arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard

 Documentation/devicetree/bindings/arm/fsl.yaml     |   7 +
 .../devicetree/bindings/net/dsa/nxp,sja1105.yaml   |   2 -
 arch/arm64/boot/dts/freescale/Makefile             |   2 +
 .../freescale/imx8dxl-hummingboard-telematics.dts  | 536 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi  | 458 ++++++++++++++++++
 5 files changed, 1003 insertions(+), 2 deletions(-)
---
base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
change-id: 20260408-imx8dxl-sr-som-f141ec343173

Best regards,
-- 
Josua Mayer <josua@solid-run.com>



^ permalink raw reply

* [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Josua Mayer @ 2026-04-09 12:34 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
	linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev, Josua Mayer
In-Reply-To: <20260409-imx8dxl-sr-som-v2-0-83ff20629ba0@solid-run.com>

Add support for the SolidRun i.MX8DXL System-on-Module (revision 2.1)
and its corresponding evaluation carrier board, the HummingBoard
Telematics (revision 2.0).

The SoM features:
- eMMC
- GNSS with 1PPS
- V2X DSRC Radio
- Secure Element for V2X Applications
- Inertial Sensor
- Pressure Sensor
- Compass

The HummingBoard Telematics carrier board features:
- Cellular Modem
- WiFi & Bluetooth
- RTC with backup battery
- CAN
- 100Base-TX Ethernet
- 100Base-T1 Ethernet
- Multi-interface I/O connector
- Multi-interface add-on board connector

The multi-interface I/O connector supplies power and provides basic I/O
(Console UART, 100Base-TX, 100Base-T1, CAN, and power-supply logic level
GPIOs). The SolidRun Evaluation Kit includes a suitable cable and
adapter board that breaks these out into RJ45, USB Type-A, microUSB
Console, and Terminal Block connectors.

The multi-interface add-on board connector provides additional
interfaces (4x 100Base-T1, 2x SGMII, USB 2.0 shared with the cellular
modem, CAN, MDIO, SPI, UART, PCIe, I2C, and GPIO). These add-on
interfaces are disabled by default in the base device tree and are
intended to be enabled and extended via device tree overlays.

Note that a few components physically present on the SoM were omitted
from this description due to a lack of upstream bindings and drivers:
- Pressure Sensor
- V2X DSRC Radio
- Secure Element

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
 arch/arm64/boot/dts/freescale/Makefile             |   2 +
 .../freescale/imx8dxl-hummingboard-telematics.dts  | 536 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi  | 458 ++++++++++++++++++
 3 files changed, 996 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 700bab4d3e600..12b946c08400b 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -111,6 +111,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx8dxl-evk.dtb
 
 imx8dxl-evk-pcie-ep-dtbs += imx8dxl-evk.dtb imx-pcie0-ep.dtbo
 dtb-$(CONFIG_ARCH_MXC) += imx8dxl-evk-pcie-ep.dtb
+DTC_FLAGS_imx8dxl-hummingboard-telematics := -@
+dtb-$(CONFIG_ARCH_MXC) += imx8dxl-hummingboard-telematics.dtb
 
 dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdp-mba8xx.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdps-mb-smarc-2.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-hummingboard-telematics.dts b/arch/arm64/boot/dts/freescale/imx8dxl-hummingboard-telematics.dts
new file mode 100644
index 0000000000000..ae23eade64244
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-hummingboard-telematics.dts
@@ -0,0 +1,536 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022-2026 Josua Mayer <josua@solid-run.com>
+ */
+
+/dts-v1/;
+
+#include "imx8dxl-sr-som.dtsi"
+
+/ {
+	compatible = "solidrun,imx8dxl-hummingboard-telematics",
+		     "solidrun,imx8dxl-sr-som", "fsl,imx8dxl";
+	model = "SolidRun i.MX8DXL HummingBoard Telematics";
+
+	aliases {
+		/* override ethernat aliases from imx8dxl.dtsi */
+		ethernet0 = &eqos;
+		/delete-property/ ethernet1;
+		gpio8 = &tca6408_u2;
+		mmc2 = &usdhc3;
+		rtc0 = &carrier_rtc;
+		rtc1 = &rtc;
+		serial1 = &lpuart1;
+	};
+
+	v_1_1: regulator-1-1 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v1";
+		pinctrl-0 = <&regulator_1v1_pins>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-max-microvolt = <1100000>;
+		regulator-min-microvolt = <1100000>;
+		vin-supply = <&v_5_0>;
+		gpio = <&lsio_gpio4 5 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_5_0: regulator-5-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "5v0";
+		regulator-max-microvolt = <5000000>;
+		regulator-min-microvolt = <5000000>;
+	};
+
+	/* can transceiver builtin regulator (STBN1 pin) */
+	reg_flexcan1_stby: regulator-flexcan1-standby {
+		compatible = "regulator-fixed";
+		regulator-name = "flexcan1-standby";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		gpio = <&tca6408_u2 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	/* can transceiver builtin regulator (STBN2 pin) */
+	reg_flexcan2_stby: regulator-flexcan2-standby {
+		compatible = "regulator-fixed";
+		regulator-name = "flexcan2-standby";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		gpio = <&tca6408_u2 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	modem_vbat: regulator-modem-vbat {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		pinctrl-0 = <&regulator_modem_vbat_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <3600000>;
+		regulator-min-microvolt = <3600000>;
+		vin-supply = <&v_5_0>;
+		gpio = <&lsio_gpio0 14 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vbus1: regulator-vbus-1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus1";
+		pinctrl-0 = <&regulator_usb1_vbus_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <5000000>;
+		regulator-min-microvolt = <5000000>;
+		gpio = <&lsio_gpio0 16 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	usdhc3_pwrseq: usdhc3-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&lsio_gpio0 15 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&dma_apbh {
+	status = "disabled";
+};
+
+&eqos {
+	/* delays are added by connected ethernet-switch cpu port */
+	phy-mode = "rgmii";
+	pinctrl-0 = <&eqos_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fixed-link {
+		full-duplex;
+		speed = <1000>;
+	};
+};
+
+&flexcan1 {
+	pinctrl-0 = <&flexcan1_pins>;
+	pinctrl-names = "default";
+	xceiver-supply = <&reg_flexcan1_stby>;
+	status = "okay";
+
+	can-transceiver {
+		max-bitrate = <5000000>;
+	};
+};
+
+&flexcan2 {
+	pinctrl-0 = <&flexcan2_pins>;
+	pinctrl-names = "default";
+	xceiver-supply = <&reg_flexcan2_stby>;
+	status = "okay";
+
+	can-transceiver {
+		max-bitrate = <5000000>;
+	};
+};
+
+&i2c2 {
+	/* routed to J14: SDA(51), SCL(53) */
+
+	/* regulator@18 */
+
+	tca6408_u2: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		#gpio-cells = <2>;
+		gpio-controller;
+		gpio-line-names = "DIG_IN1", "DIG_IN2", "CAN_STNB1", "CAN_STNB2",
+				  "DIG_OUT1", "DIG_OUT2", "", "";
+		interrupts-extended = <&lsio_gpio0 20 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-0 = <&tca6408_u2_int_pins>;
+		pinctrl-names = "default";
+	};
+
+	carrier_rtc: rtc@32 {
+		compatible = "epson,rx8111";
+		reg = <0x32>;
+	};
+};
+
+&iomuxc {
+	bluetooth_pins: pinctrl-bluetooth-grp {
+		fsl,pins = <
+			/* BT_REG_ON: io without pull (module integrates pd) */
+			IMX8DXL_SPI3_SCK_LSIO_GPIO0_IO13			0x0000061
+		>;
+	};
+
+	eqos_pins: pinctrl-eqos-grp {
+		fsl,pins = <
+			/* MDIO to Switch */
+			/* enet0 mdio pads supplied with 3.3v */
+			/* IMX8DXL_COMP_CTL_GPIO_1V8_3V3_GPIOCT */
+			IMX8DXL_ENET0_MDC_CONN_EQOS_MDC				0x06000020
+			IMX8DXL_ENET0_MDIO_CONN_EQOS_MDIO			0x06000020
+			/* RGMII to Switch */
+			IMX8DXL_ENET1_RGMII_TX_CTL_CONN_EQOS_RGMII_TX_CTL	0x06000020
+			IMX8DXL_ENET1_RGMII_TXC_CONN_EQOS_RGMII_TXC		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD0_CONN_EQOS_RGMII_TXD0		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD1_CONN_EQOS_RGMII_TXD1		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD2_CONN_EQOS_RGMII_TXD2		0x06000020
+			IMX8DXL_ENET1_RGMII_TXD3_CONN_EQOS_RGMII_TXD3		0x06000020
+			IMX8DXL_ENET1_RGMII_RXC_CONN_EQOS_RGMII_RXC		0x06000020
+			IMX8DXL_ENET1_RGMII_RX_CTL_CONN_EQOS_RGMII_RX_CTL	0x06000020
+			IMX8DXL_ENET1_RGMII_RXD0_CONN_EQOS_RGMII_RXD0		0x06000020
+			IMX8DXL_ENET1_RGMII_RXD1_CONN_EQOS_RGMII_RXD1		0x06000020
+			IMX8DXL_ENET1_RGMII_RXD2_CONN_EQOS_RGMII_RXD2		0x06000020
+			IMX8DXL_ENET1_RGMII_RXD3_CONN_EQOS_RGMII_RXD3		0x06000020
+		>;
+	};
+
+	flexcan1_pins: pinctrl-flexcan1-grp {
+		fsl,pins = <
+			IMX8DXL_FLEXCAN0_TX_ADMA_FLEXCAN0_TX			0x00000021
+			IMX8DXL_FLEXCAN0_RX_ADMA_FLEXCAN0_RX			0x00000021
+		>;
+	};
+
+	flexcan2_pins: pinctrl-flexcan2-grp {
+		fsl,pins = <
+			IMX8DXL_FLEXCAN1_TX_ADMA_FLEXCAN1_TX			0x00000021
+			IMX8DXL_FLEXCAN1_RX_ADMA_FLEXCAN1_RX			0x00000021
+		>;
+	};
+
+	lpspi0_pins: pinctrl-lpspi0-grp {
+		fsl,pins = <
+			IMX8DXL_SPI0_SCK_ADMA_SPI0_SCK				0x600004c
+			IMX8DXL_SPI0_SDO_ADMA_SPI0_SDO				0x600004c
+			IMX8DXL_SPI0_SDI_ADMA_SPI0_SDI				0x600004c
+			IMX8DXL_SPI0_CS0_LSIO_GPIO1_IO08			0x0000021
+			IMX8DXL_SPI0_CS1_LSIO_GPIO1_IO07			0x0000021
+		>;
+	};
+
+	lpuart1_pins: pinctrl-lpuart1-grp {
+		fsl,pins = <
+			IMX8DXL_UART1_RX_ADMA_UART1_RX				0x06000020
+			IMX8DXL_UART1_TX_ADMA_UART1_TX				0x06000020
+			IMX8DXL_UART1_CTS_B_ADMA_UART1_CTS_B			0x06000020
+			IMX8DXL_UART1_RTS_B_ADMA_UART1_RTS_B			0x06000020
+		>;
+	};
+
+	modem_pins: pinctrl-lte-grp {
+		fsl,pins = <
+			/* modem RESET_N: io open drain drive 2mA */
+			IMX8DXL_ADC_IN3_LSIO_GPIO1_IO11	0x2000061
+
+			/* modem PWRKEY: io open drain with pull-up, drive 2mA */
+			IMX8DXL_ADC_IN2_LSIO_GPIO1_IO12	0x2000021
+		>;
+	};
+
+	regulator_1v1_pins: pinctrl-regulator-1-1-grp {
+		fsl,pins = <
+			/* SW_PE: io without pull-up */
+			IMX8DXL_USB_SS3_TC2_LSIO_GPIO4_IO05			0x0000061
+		>;
+	};
+
+	regulator_modem_vbat_pins: pinctrl-regulator-modem-vbat-grp {
+		fsl,pins = <
+			/*
+			 * RF_PWR: io without pull-up,
+			 * has either external pull-up (R1117) or pull-down (R1118).
+			 * With pull-up Modem will boot at system power-up,
+			 * with pull-down modem will enter power-down mode once
+			 * vbat is enabled -> toggle pwrkey to boot modem.
+			 * Hence pull-up (R1117) is preferred.
+			 */
+			IMX8DXL_SPI3_SDO_LSIO_GPIO0_IO14			0x0000061
+		>;
+	};
+
+	regulator_usb1_vbus_pins: pinctrl-regulator-usb1-vbus-grp {
+		fsl,pins = <
+			/* regulator enable: open-drain with pull-up & low drive strength */
+			IMX8DXL_SPI3_CS0_LSIO_GPIO0_IO16			0x2000021
+		>;
+	};
+
+	switch_pins: pinctrl-switch-grp {
+		fsl,pins = <
+			/* SW_RSTn: io without pull-up */
+			IMX8DXL_USB_SS3_TC0_LSIO_GPIO4_IO03			0x0000021
+
+			/* SW_CORE_RSTn: io without pull-up */
+			IMX8DXL_USB_SS3_TC1_LSIO_GPIO4_IO04			0x0000021
+
+			/* INT_N: io without pull-up */
+			IMX8DXL_USB_SS3_TC3_LSIO_GPIO4_IO06			0x0000021
+		>;
+	};
+
+	tca6408_u2_int_pins: pinctrl-tca6408-u2-int-grp {
+		fsl,pins = <
+			/* gpio-expander interrupt: io with pull-up */
+			IMX8DXL_MCLK_OUT0_LSIO_GPIO0_IO20			0x0000021
+		>;
+	};
+
+	usdhc3_pins: pinctrl-usdhc3-grp {
+		fsl,pins = <
+			IMX8DXL_ENET0_RGMII_TXC_CONN_USDHC2_CLK			0x06000040
+			IMX8DXL_ENET0_RGMII_TX_CTL_CONN_USDHC2_CMD		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD0_CONN_USDHC2_DATA0		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD1_CONN_USDHC2_DATA1		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD2_CONN_USDHC2_DATA2		0x00000021
+			IMX8DXL_ENET0_RGMII_TXD3_CONN_USDHC2_DATA3		0x00000021
+		>;
+	};
+
+	wifi_pins: pinctrl-wifi-grp {
+		fsl,pins = <
+			/* WL_REG_ON: io without pull (module integrates pd) */
+			IMX8DXL_SPI3_SDI_LSIO_GPIO0_IO15			0x0000061
+		>;
+	};
+};
+
+&lpspi0 {
+	cs-gpios = <&lsio_gpio1 8 GPIO_ACTIVE_LOW>, <&lsio_gpio1 7 GPIO_ACTIVE_LOW>;
+	pinctrl-0 = <&lpspi0_pins>, <&switch_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	ethernet-switch@0 {
+		compatible = "nxp,sja1110a";
+		reg = <0>;
+		reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
+		spi-max-frequency = <4000000>;
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* 100Base-TX on connector J26 */
+			port@1 {
+				reg = <0x1>;
+				label = "lan1";
+				phy-handle = <&switch_port1_base_tx_phy>;
+				phy-mode = "internal";
+				status = "okay";
+			};
+
+			/* CPU */
+			port@2 {
+				reg = <0x2>;
+				ethernet = <&eqos>;
+				label = "cpu";
+				phy-mode = "rgmii-id";
+				rx-internal-delay-ps = <2000>;
+				tx-internal-delay-ps = <2000>;
+				status = "okay";
+
+				fixed-link {
+					full-duplex;
+					speed = <1000>;
+				};
+			};
+
+			/* sgmii on addon board connector J21 */
+			port@3 {
+				reg = <0x3>;
+				label = "lan3";
+				status = "disabled";
+			};
+
+			/* sgmii on addon board connector J21 */
+			port@4 {
+				reg = <0x4>;
+				label = "lan4";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@5 {
+				reg = <0x5>;
+				label = "trx1";
+				phy-handle = <&switch_port5_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@6 {
+				reg = <0x6>;
+				label = "trx2";
+				phy-handle = <&switch_port6_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@7 {
+				reg = <0x7>;
+				label = "trx3";
+				phy-handle = <&switch_port7_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@8 {
+				reg = <0x8>;
+				label = "trx4";
+				phy-handle = <&switch_port8_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100base-t1 on addon board connector J21 */
+			port@9 {
+				reg = <0x9>;
+				label = "trx5";
+				phy-handle = <&switch_port9_base_t1_phy>;
+				phy-mode = "internal";
+				status = "disabled";
+			};
+
+			/* 100Base-T1 on connector J26 */
+			port@a {
+				reg = <0xa>;
+				label = "trx6";
+				phy-handle = <&switch_port10_base_t1_phy>;
+				phy-mode = "internal";
+				status = "okay";
+			};
+		};
+
+		mdios {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			mdio@0 {
+				compatible = "nxp,sja1110-base-t1-mdio";
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port5_base_t1_phy: ethernet-phy@1 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x1>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port6_base_t1_phy: ethernet-phy@2 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x2>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port7_base_t1_phy: ethernet-phy@3 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x3>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port8_base_t1_phy: ethernet-phy@4 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x4>;
+					status = "disabled";
+				};
+
+				/* 100base-t1 on addon board connector J21 */
+				switch_port9_base_t1_phy: ethernet-phy@5 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x5>;
+					status = "disabled";
+				};
+
+				/* 100Base-T1 on connector J26 */
+				switch_port10_base_t1_phy: ethernet-phy@6 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0x6>;
+				};
+			};
+
+			mdio@1 {
+				compatible = "nxp,sja1110-base-tx-mdio";
+				reg = <1>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* 100Base-TX on connector J26 */
+				switch_port1_base_tx_phy: ethernet-phy@1 {
+					reg = <0x1>;
+				};
+			};
+		};
+	};
+};
+
+/* bluetooth */
+&lpuart1 {
+	pinctrl-0 = <&lpuart1_pins>, <&bluetooth_pins>;
+	pinctrl-names = "default";
+	uart-has-rtscts;
+	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm4345c5";
+		/* Murata 1MW module supports max. 3M baud */
+		max-speed = <3000000>;
+		shutdown-gpios = <&lsio_gpio0 13 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&usbotg1 {
+	vbus-supply = <&vbus1>;
+};
+
+/* cellular modem */
+&usbotg2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	adp-disable;
+	disable-over-current;
+	dr_mode = "host";
+	hnp-disable;
+	pinctrl-0 = <&modem_pins>;
+	pinctrl-names = "default";
+	power-active-high;
+	srp-disable;
+	vbus-supply = <&v_5_0>;
+	status = "okay";
+
+	usb-device@1 {
+		compatible = "usb2c7c,125";
+		reg = <1>;
+		reset-duration-us = <150000>;
+		reset-gpios = <&lsio_gpio1 11 GPIO_ACTIVE_LOW>;
+		vbus-supply = <&v_3_3>;
+		vdd-supply = <&modem_vbat>;
+	};
+};
+
+&usbphy2 {
+	status = "okay";
+};
+
+/* WiFi */
+&usdhc3 {
+	bus-width = <4>;
+	mmc-pwrseq = <&usdhc3_pwrseq>;
+	non-removable;
+	no-sd;
+	pinctrl-0 = <&usdhc3_pins>, <&wifi_pins>;
+	pinctrl-names = "default";
+	vmmc-supply = <&v_3_3>;
+	vqmmc-supply = <&v_1_8>;
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi
new file mode 100644
index 0000000000000..93a0eb4d7f770
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022-2026 Josua Mayer <josua@solid-run.com>
+ */
+
+#include "imx8dxl.dtsi"
+/ {
+	compatible = "solidrun,imx8dxl-sr-som", "fsl,imx8dxl";
+	model = "SolidRun i.MX8DXL SoM";
+
+	aliases {
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		mmc0 = &usdhc1;
+		mmc1 = &usdhc2;
+		serial0 = &lpuart0;
+		serial2 = &lpuart2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	imx8dxl-cm4 {
+		compatible = "fsl,imx8qxp-cm4";
+		clocks = <&clk_dummy>;
+		mboxes = <&lsio_mu5 0 1 &lsio_mu5 1 1 &lsio_mu5 3 1>;
+		mbox-names = "tx", "rx", "rxdb";
+		memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>,
+				<&vdev1vring0>, <&vdev1vring1>, <&rsc_table>;
+		power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>;
+		fsl,entry-address = <0x34fe0000>;
+		fsl,resource-id = <IMX_SC_R_M4_0_PID0>;
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&lsio_gpio2 6 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&gnss_pps_pins>;
+		pinctrl-names = "default";
+	};
+
+	v_1_2: regulator-1-2 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v2";
+		pinctrl-0 = <&regulator_1_2_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <1200000>;
+		regulator-min-microvolt = <1200000>;
+		gpio = <&lsio_gpio1 13 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_1_6: regulator-1-6 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v6";
+		pinctrl-0 = <&regulator_1_6_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <1600000>;
+		regulator-min-microvolt = <1600000>;
+		vin-supply = <&v_1_8>;
+		gpio = <&lsio_gpio1 14 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_1_8: regulator-1-8 {
+		compatible = "regulator-fixed";
+		regulator-name = "1v8";
+		regulator-max-microvolt = <1800000>;
+		regulator-min-microvolt = <1800000>;
+	};
+
+	v_1_8_se: regulator-1-8-secure-element {
+		compatible = "regulator-fixed";
+		regulator-name = "1v8-se";
+		pinctrl-0 = <&regulator_1_8_se_pins>;
+		pinctrl-names = "default";
+		regulator-max-microvolt = <1800000>;
+		regulator-min-microvolt = <1800000>;
+		vin-supply = <&v_1_8>;
+		gpio = <&lsio_gpio3 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	v_3_3: regulator-3-3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3v3";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+	};
+
+	reserved-memory {
+		ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		/* global autoconfigured region for contiguous allocations */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x98000000 0 0x14000000>;
+			reusable;
+			size = <0 0x14000000>;
+			linux,cma-default;
+		};
+
+		vdev0vring0: memory0@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_table: memory-rsc-table@900ff000 {
+			reg = <0 0x900ff000 0 0x1000>;
+			no-map;
+		};
+
+		vdevbuffer: memory-vdevbuffer@90400000 {
+			compatible = "shared-dma-pool";
+			reg = <0 0x90400000 0 0x100000>;
+			no-map;
+		};
+
+		/*
+		 * Memory reserved for optee usage. Please do not use.
+		 * This will be automatically added to dtb if OP-TEE is installed.
+		 * optee@96000000 {
+		 *     reg = <0 0x96000000 0 0x2000000>;
+		 *     no-map;
+		 * };
+		 */
+	};
+
+	memory@80000000 {
+		reg = <0x00000000 0x80000000 0 0x40000000>;
+		device_type = "memory";
+	};
+};
+
+&i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-1 = <&i2c2_gpio_pins>;
+	pinctrl-names = "default", "gpio";
+	scl-gpios = <&lsio_gpio3 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&lsio_gpio3 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	status = "okay";
+};
+
+&i2c3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c3_pins>;
+	pinctrl-1 = <&i2c3_gpio_pins>;
+	pinctrl-names = "default", "gpio";
+	scl-gpios = <&lsio_gpio3 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&lsio_gpio3 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	status = "okay";
+
+	magnetometer@1e {
+		compatible = "st,iis2mdc";
+		reg = <0x1e>;
+		interrupt-parent = <&lsio_gpio2>;
+		interrupts = <10 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-0 = <&magnetometer_pins>;
+		pinctrl-names = "default";
+		st,drdy-int-pin = <1>;
+	};
+
+	/* pressure-sensor@5c */
+
+	inertial-sensor@6b {
+		compatible = "st,ism330dhcx";
+		reg = <0x6b>;
+		interrupt-parent = <&lsio_gpio2>;
+		interrupts = <11 IRQ_TYPE_EDGE_RISING>;
+		pinctrl-0 = <&imu_pins>;
+		pinctrl-names = "default";
+		st,drdy-int-pin = <1>;
+	};
+};
+
+&iomuxc {
+	pinctrl-0 = <&pinctrl_hog>;
+	pinctrl-names = "default";
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			IMX8DXL_COMP_CTL_GPIO_1V8_3V3_GPIORHB_PAD	0x000514a0
+			IMX8DXL_COMP_CTL_GPIO_1V8_3V3_GPIORHK_PAD	0x000014a0
+		>;
+	};
+
+	dsrc_pins: pinctrl-dsrc-grp {
+		fsl,pins = <
+			/* reset: io without pull */
+			IMX8DXL_ADC_IN0_LSIO_GPIO1_IO10			0x0000060
+
+			/*
+			 * boot0: io without pull
+			 * After reset, this pin selects radio boot media:
+			 * - 0: flash spi
+			 * - 1: slave sdio
+			 * Once the firmware boots however, the radio controls
+			 * this pin for flow-control to signal readiness.
+			 */
+			IMX8DXL_ADC_IN1_LSIO_GPIO1_IO09			0x0000060
+		>;
+	};
+
+	gnss_pins: pinctrl-gnss-grp {
+		fsl,pins = <
+			/* gps reset: input with pull-up */
+			IMX8DXL_SNVS_TAMPER_OUT4_LSIO_GPIO2_IO08_IN	0x0000021
+			/* gps interrupt: io without pull-up */
+			IMX8DXL_SNVS_TAMPER_IN0_LSIO_GPIO2_IO09_IN	0x0000061
+		>;
+	};
+
+	gnss_pps_pins: pinctrl-gnss-pps-grp {
+		fsl,pins = <
+			/* gps timepulse: input without pull-up */
+			IMX8DXL_SNVS_TAMPER_OUT2_LSIO_GPIO2_IO06_IN	0x0000061
+		>;
+	};
+
+	i2c2_gpio_pins: pinctrl-i2c2-gpio-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_SCK_LSIO_GPIO3_IO00		0x00000021
+			/* io with pull-up, weak drive, open-drain */
+			IMX8DXL_SPI1_SDO_LSIO_GPIO3_IO01		0x02000021
+		>;
+	};
+
+	i2c2_pins: pinctrl-i2c2-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_SCK_ADMA_I2C2_SDA			0x06000021
+			IMX8DXL_SPI1_SDO_ADMA_I2C2_SCL			0x06000021
+		>;
+	};
+
+	i2c3_gpio_pins: pinctrl-i2c3-gpio-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_CS0_LSIO_GPIO3_IO03		0x00000021
+			/* io with pull-up, weak drive, open-drain */
+			IMX8DXL_SPI1_SDI_LSIO_GPIO3_IO02		0x02000021
+		>;
+	};
+
+	i2c3_pins: pinctrl-i2c3-grp {
+		fsl,pins = <
+			/* io with pull-up and weak drive */
+			IMX8DXL_SPI1_CS0_ADMA_I2C3_SDA			0x06000021
+			IMX8DXL_SPI1_SDI_ADMA_I2C3_SCL			0x06000021
+		>;
+	};
+
+	imu_pins: pinctrl-imu-grp {
+		fsl,pins = <
+			/* interrupt: io with pull-down */
+			IMX8DXL_SNVS_TAMPER_IN2_LSIO_GPIO2_IO11_IN	0x0000041
+		>;
+	};
+
+	lpspi2_pins: pinctrl-lpspi2-grp {
+		fsl,pins = <
+			IMX8DXL_USDHC1_RESET_B_ADMA_SPI2_SCK		0x600004c
+			IMX8DXL_USDHC1_VSELECT_ADMA_SPI2_SDO		0x600004c
+			IMX8DXL_USDHC1_WP_ADMA_SPI2_SDI			0x600004c
+			IMX8DXL_USDHC1_CD_B_LSIO_GPIO4_IO22		0x6000021
+		>;
+	};
+
+	lpuart0_pins: pinctrl-lpuart0-grp {
+		fsl,pins = <
+			IMX8DXL_UART0_RX_ADMA_UART0_RX			0x06000020
+			IMX8DXL_UART0_TX_ADMA_UART0_TX			0x06000020
+		>;
+	};
+
+	lpuart2_pins: pinctrl-lpuart2-grp {
+		fsl,pins = <
+			IMX8DXL_UART2_TX_ADMA_UART2_TX			0x06000020
+			IMX8DXL_UART2_RX_ADMA_UART2_RX			0x06000020
+		>;
+	};
+
+	magnetometer_pins: pinctrl-magnetometer-grp {
+		fsl,pins = <
+			/* interrupt: io with pull-down */
+			IMX8DXL_SNVS_TAMPER_IN1_LSIO_GPIO2_IO10_IN	0x0000041
+		>;
+	};
+
+	regulator_1_2_pins: pinctrl-regulator-1-2-grp {
+		fsl,pins = <
+			/* io without pull-up */
+			/* has etxernal pull-down */
+			IMX8DXL_ADC_IN5_LSIO_GPIO1_IO13			0x0000061
+		>;
+	};
+
+	regulator_1_6_pins: pinctrl-regulator-1-6-grp {
+		fsl,pins = <
+			/* io without pull-up */
+			/* has etxernal pull-down */
+			IMX8DXL_ADC_IN4_LSIO_GPIO1_IO14			0x0000061
+		>;
+	};
+
+	regulator_1_8_se_pins: pinctrl-regulator-1-8-secure-element-grp {
+		fsl,pins = <
+			/* v2x-secure-element power switch: io with pull-down */
+			IMX8DXL_QSPI0B_DATA0_LSIO_GPIO3_IO18		0x0000041
+		>;
+	};
+
+	se_pins: pinctrl-secure-element-grp {
+		fsl,pins = <
+			/* v2x-secure-element reset: io with pull-up */
+			IMX8DXL_QSPI0B_DATA1_LSIO_GPIO3_IO19		0x0000021
+
+			/*
+			 * v2x-secure-element gpio0: io with pull-up
+			 * pulled low by sxf after boot indicating ready for commands
+			 */
+			IMX8DXL_QSPI0B_DATA2_LSIO_GPIO3_IO20		0x0000021
+
+			/* v2x-secure-element gpio1: io with pull-up */
+			IMX8DXL_QSPI0B_DATA3_LSIO_GPIO3_IO21		0x0000021
+		>;
+	};
+
+	usdhc1_pins: pinctrl-usdhc1-grp {
+		fsl,pins = <
+			IMX8DXL_EMMC0_CLK_CONN_EMMC0_CLK		0x06000041
+			IMX8DXL_EMMC0_CMD_CONN_EMMC0_CMD		0x00000021
+			IMX8DXL_EMMC0_DATA0_CONN_EMMC0_DATA0		0x00000021
+			IMX8DXL_EMMC0_DATA1_CONN_EMMC0_DATA1		0x00000021
+			IMX8DXL_EMMC0_DATA2_CONN_EMMC0_DATA2		0x00000021
+			IMX8DXL_EMMC0_DATA3_CONN_EMMC0_DATA3		0x00000021
+			IMX8DXL_EMMC0_DATA4_CONN_EMMC0_DATA4		0x00000021
+			IMX8DXL_EMMC0_DATA5_CONN_EMMC0_DATA5		0x00000021
+			IMX8DXL_EMMC0_DATA6_CONN_EMMC0_DATA6		0x00000021
+			IMX8DXL_EMMC0_DATA7_CONN_EMMC0_DATA7		0x00000021
+			IMX8DXL_EMMC0_STROBE_CONN_EMMC0_STROBE		0x00000041
+			IMX8DXL_EMMC0_RESET_B_CONN_EMMC0_RESET_B	0x00000061
+		>;
+	};
+
+	usdhc2_pins: pinctrl-usdhc2-grp {
+		fsl,pins = <
+			IMX8DXL_ENET0_RGMII_RXC_CONN_USDHC1_CLK		0x06000040
+			IMX8DXL_ENET0_RGMII_RX_CTL_CONN_USDHC1_CMD	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD0_CONN_USDHC1_DATA0	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD1_CONN_USDHC1_DATA1	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD2_CONN_USDHC1_DATA2	0x00000021
+			IMX8DXL_ENET0_RGMII_RXD3_CONN_USDHC1_DATA3	0x00000021
+		>;
+	};
+};
+
+&lpspi2 {
+	cs-gpios = <&lsio_gpio4 22 GPIO_ACTIVE_LOW>;
+	num-cs = <1>;
+	pinctrl-0 = <&lpspi2_pins>, <&se_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+/* console */
+&lpuart0 {
+	pinctrl-0 = <&lpuart0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+/* gnss */
+&lpuart2 {
+	pinctrl-0 = <&lpuart2_pins>, <&gnss_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&lsio_gpio3 {
+	gpio-line-names = "", "", "", "", "", "", "", "",
+			  "", "", "", "", "", "", "", "",
+			  "", "", "", "SXF_RST", "SXF_GPIO0", "SXF_GPIO1", "", "",
+			  "", "", "", "", "", "", "", "";
+};
+
+&lsio_mu5 {
+	status = "okay";
+};
+
+/* OTG port for boot */
+&usbotg1 {
+	adp-disable;
+	disable-over-current;
+	dr_mode = "peripheral";
+	hnp-disable;
+	power-active-high;
+	srp-disable;
+	status = "okay";
+};
+
+&usbphy1 {
+	status = "okay";
+};
+
+/* eMMC */
+&usdhc1 {
+	bus-width = <8>;
+	cap-mmc-hw-reset;
+	non-removable;
+	no-sd;
+	no-sdio;
+	pinctrl-0 = <&usdhc1_pins>;
+	pinctrl-1 = <&usdhc1_pins>;
+	pinctrl-2 = <&usdhc1_pins>;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	vmmc-supply = <&v_3_3>;
+	vqmmc-supply = <&v_1_8>;
+	status = "okay";
+};
+
+/* DSRC Radio */
+&usdhc2 {
+	bus-width = <4>;
+	keep-power-in-suspend;
+	max-frequency = <40000000>;
+	non-removable;
+	no-sd;
+	pinctrl-0 = <&usdhc2_pins>, <&dsrc_pins>;
+	pinctrl-names = "default";
+	vmmc-supply = <&v_3_3>;
+	vqmmc-supply = <&v_1_8>;
+	status = "okay";
+};

-- 
2.51.0



^ permalink raw reply related

* Re: [PATCH 1/3] dt-bindings: iommu: arm-smmu-v3: Allow PMU child nodes
From: Peng Fan @ 2026-04-09 12:45 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Mark Rutland, linux-arm-kernel,
	iommu, devicetree, linux-kernel, linux-perf-users, Peng Fan
In-Reply-To: <20260409-outstanding-arboreal-peacock-2de6f1@quoll>

On Thu, Apr 09, 2026 at 10:10:38AM +0200, Krzysztof Kozlowski wrote:
>On Wed, Apr 08, 2026 at 03:51:15PM +0800, Peng Fan (OSS) wrote:
>> From: Peng Fan <peng.fan@nxp.com>
>> 
>> The Arm SMMU v3 specification defines an optional PMCG (Performance
>
>"optional" in a meaning some SMMUv3 implementations do not have it?

Per SMMUv3 architecture:
Performance monitoring facilities are optional. When implemented, the SMMU has
one or more Performance Monitor Counter Groups (PMCG) associated with it.

>
>> Monitor Control Group) block. Per MMU-700 TRM, it has three 64KB pages,
>> with TCU Performance Monitor Counter Group (PMCG) registers starting at
>> offset 0x02000 in page 0. So PMCG could be described as a child node of the
>> SMMU in Devicetree.
>> 
>> Add a patternProperties entry to the arm,smmu-v3 binding to allow child
>> nodes matching "pmu@<addr>" and reference the existing
>> arm,smmu-v3-pmcg.yaml schema.
>> 
>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>> ---
>>  Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml | 10 ++++++++++
>>  1 file changed, 10 insertions(+)
>> 
>> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
>> index 82957334bea24402b583e47eb61b5724c91e4378..1d09c5476e5f1a7c3e5c935b677641ee6cc9897e 100644
>> --- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
>> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml
>> @@ -50,6 +50,10 @@ properties:
>>              - cmdq-sync   # CMD_SYNC complete
>>              - priq        # PRI Queue not empty
>>  
>> +  '#address-cells': true
>
>Instead enum [1, 2]
>
>> +  '#size-cells': true
>
>Same here
>
>> +  ranges: true
>
>I guess only one mapping is allowed so:
>maxItems: 1

Accept above three comments.

>
>> +
>>    '#iommu-cells':
>>      const: 1
>>  
>> @@ -83,6 +87,12 @@ properties:
>>        register access with page 0 offsets. Set for Cavium ThunderX2 silicon that
>>        doesn't support SMMU page1 register space.
>>  
>> +patternProperties:
>> +  '^pmu@[0-9a-f]+$':
>> +    type: object
>> +    $ref: /schemas/perf/arm,smmu-v3-pmcg.yaml#
>> +    unevaluatedProperties: false
>
>Please add another example with 4-space indentation.

ok.

Thanks,
Peng

>
>> +
>>  allOf:
>>    - if:
>>        not:
>> 
>> -- 
>> 2.37.1
>> 
>


^ permalink raw reply

* Re: [PATCH v2 3/3] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Andrew Lunn @ 2026-04-09 12:46 UTC (permalink / raw)
  To: Josua Mayer
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
	Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Yazan Shhady, Mikhail Anikin, Alexander Dahl,
	devicetree, linux-kernel, imx, linux-arm-kernel, Vladimir Oltean,
	Conor Dooley, Krzysztof Kozlowski, netdev
In-Reply-To: <20260409-imx8dxl-sr-som-v2-3-83ff20629ba0@solid-run.com>

> +&eqos {
> +	/* delays are added by connected ethernet-switch cpu port */
> +	phy-mode = "rgmii";
> +	pinctrl-0 = <&eqos_pins>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +
> +	fixed-link {
> +		full-duplex;
> +		speed = <1000>;
> +	};
> +};


> +	ethernet-switch@0 {
> +		compatible = "nxp,sja1110a";
> +		reg = <0>;
> +		reset-gpios = <&lsio_gpio4 3 GPIO_ACTIVE_LOW>;
> +		spi-max-frequency = <4000000>;
> +
> +		ethernet-ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			/* 100Base-TX on connector J26 */
> +			port@1 {
> +				reg = <0x1>;
> +				label = "lan1";
> +				phy-handle = <&switch_port1_base_tx_phy>;
> +				phy-mode = "internal";
> +				status = "okay";
> +			};
> +
> +			/* CPU */
> +			port@2 {
> +				reg = <0x2>;
> +				ethernet = <&eqos>;
> +				label = "cpu";
> +				phy-mode = "rgmii-id";
> +				rx-internal-delay-ps = <2000>;
> +				tx-internal-delay-ps = <2000>;
> +				status = "okay";
> +
> +				fixed-link {
> +					full-duplex;
> +					speed = <1000>;
> +				};
> +			};
> +
> +			/* sgmii on addon board connector J21 */
> +			port@3 {
> +				reg = <0x3>;
> +				label = "lan3";
> +				status = "disabled";
> +			};
> +
> +			/* sgmii on addon board connector J21 */
> +			port@4 {
> +				reg = <0x4>;
> +				label = "lan4";
> +				status = "disabled";
> +			};
> +
> +			/* 100base-t1 on addon board connector J21 */
> +			port@5 {
> +				reg = <0x5>;
> +				label = "trx1";
> +				phy-handle = <&switch_port5_base_t1_phy>;
> +				phy-mode = "internal";
> +				status = "disabled";
> +			};
> +
> +			/* 100base-t1 on addon board connector J21 */
> +			port@6 {
> +				reg = <0x6>;
> +				label = "trx2";
> +				phy-handle = <&switch_port6_base_t1_phy>;
> +				phy-mode = "internal";
> +				status = "disabled";
> +			};
> +
> +			/* 100base-t1 on addon board connector J21 */
> +			port@7 {
> +				reg = <0x7>;
> +				label = "trx3";
> +				phy-handle = <&switch_port7_base_t1_phy>;
> +				phy-mode = "internal";
> +				status = "disabled";
> +			};
> +
> +			/* 100base-t1 on addon board connector J21 */
> +			port@8 {
> +				reg = <0x8>;
> +				label = "trx4";
> +				phy-handle = <&switch_port8_base_t1_phy>;
> +				phy-mode = "internal";
> +				status = "disabled";
> +			};
> +
> +			/* 100base-t1 on addon board connector J21 */
> +			port@9 {
> +				reg = <0x9>;
> +				label = "trx5";
> +				phy-handle = <&switch_port9_base_t1_phy>;
> +				phy-mode = "internal";
> +				status = "disabled";
> +			};
> +
> +			/* 100Base-T1 on connector J26 */
> +			port@a {
> +				reg = <0xa>;
> +				label = "trx6";
> +				phy-handle = <&switch_port10_base_t1_phy>;
> +				phy-mode = "internal";
> +				status = "okay";
> +			};
> +		};
> +
> +		mdios {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			mdio@0 {
> +				compatible = "nxp,sja1110-base-t1-mdio";
> +				reg = <0>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				/* 100base-t1 on addon board connector J21 */
> +				switch_port5_base_t1_phy: ethernet-phy@1 {
> +					compatible = "ethernet-phy-ieee802.3-c45";
> +					reg = <0x1>;
> +					status = "disabled";
> +				};
> +
> +				/* 100base-t1 on addon board connector J21 */
> +				switch_port6_base_t1_phy: ethernet-phy@2 {
> +					compatible = "ethernet-phy-ieee802.3-c45";
> +					reg = <0x2>;
> +					status = "disabled";
> +				};
> +
> +				/* 100base-t1 on addon board connector J21 */
> +				switch_port7_base_t1_phy: ethernet-phy@3 {
> +					compatible = "ethernet-phy-ieee802.3-c45";
> +					reg = <0x3>;
> +					status = "disabled";
> +				};
> +
> +				/* 100base-t1 on addon board connector J21 */
> +				switch_port8_base_t1_phy: ethernet-phy@4 {
> +					compatible = "ethernet-phy-ieee802.3-c45";
> +					reg = <0x4>;
> +					status = "disabled";
> +				};
> +
> +				/* 100base-t1 on addon board connector J21 */
> +				switch_port9_base_t1_phy: ethernet-phy@5 {
> +					compatible = "ethernet-phy-ieee802.3-c45";
> +					reg = <0x5>;
> +					status = "disabled";
> +				};
> +
> +				/* 100Base-T1 on connector J26 */
> +				switch_port10_base_t1_phy: ethernet-phy@6 {
> +					compatible = "ethernet-phy-ieee802.3-c45";
> +					reg = <0x6>;
> +				};
> +			};
> +
> +			mdio@1 {
> +				compatible = "nxp,sja1110-base-tx-mdio";
> +				reg = <1>;
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				/* 100Base-TX on connector J26 */
> +				switch_port1_base_tx_phy: ethernet-phy@1 {
> +					reg = <0x1>;
> +				};
> +			};

For these nodes only:

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew


^ permalink raw reply

* Re: [PATCH 1/2] KVM: arm64: Factor out TG0/1 decoding of VTCR and TCR
From: Wei-Lin Chang @ 2026-04-09 12:54 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, linux-kernel, Oliver Upton, Joey Gouly,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon
In-Reply-To: <87y0izb5o6.wl-maz@kernel.org>

On Tue, Apr 07, 2026 at 08:17:29AM +0100, Marc Zyngier wrote:
> On Mon, 06 Apr 2026 17:46:17 +0100,
> Wei-Lin Chang <weilin.chang@arm.com> wrote:
> > 
> > The current code decodes TCR.TG0/TG1 and VTCR.TG0 inline at several
> > places. Extract this logic into helpers so the granule size is derived
> > in one place. This enables us to alter the effective granule size in
> > the same place, which we will need in a later patch.
> > 
> > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > ---
> >  arch/arm64/kvm/at.c     | 73 +++++++++++++++++++++++++----------------
> >  arch/arm64/kvm/nested.c | 70 ++++++++++++++++++++++++---------------
> >  2 files changed, 89 insertions(+), 54 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/at.c b/arch/arm64/kvm/at.c
> > index c5c5644b1878..ff8ba30e917b 100644
> > --- a/arch/arm64/kvm/at.c
> > +++ b/arch/arm64/kvm/at.c
> > @@ -135,14 +135,54 @@ static void compute_s1poe(struct kvm_vcpu *vcpu, struct s1_walk_info *wi)
> >  	wi->e0poe = (wi->regime != TR_EL2) && (val & TCR2_EL1_E0POE);
> >  }
> >  
> > +static unsigned int tg0_to_shift(u64 tg0)
> > +{
> 
> It'd be better to abstract these helpers a bit more by making them
> take the full TCR_ELx value, and to give them a slightly better name.
> 
> I'd suggest something like:
> 
> static unsigned int tcr_to_tg0_pgshift(u64 tcr)
> {
> 	u64 tg0 = tcr & TCR_TG0_MASK, tcr;
> 
> which makes it clear that the result is a page shift, as required by
> wi->pgshift.

Makes sense, I'll change it.

> 
> > +	switch (tg0) {
> > +	case TCR_EL1_TG0_4K:
> > +		return 12;
> > +	case TCR_EL1_TG0_16K:
> > +		return 14;
> > +	case TCR_EL1_TG0_64K:
> 
> Please don't mix the _EL1 definition and those without _EL1 in the
> same file. For a start, that's not always EL1. Also, this makes very
> hard to reason about what is shifted and what is not.

Thanks for pointing this out, will fix.

> 
> > +	default:	/* IMPDEF: treat any other value as 64k */
> > +		return 16;
> > +	}
> > +}
> > +
> > +static unsigned int tg1_to_shift(u64 tg1)
> > +{
> > +	switch (tg1) {
> > +	case TCR_EL1_TG1_4K:
> > +		return 12;
> > +	case TCR_EL1_TG1_16K:
> > +		return 14;
> > +	case TCR_EL1_TG1_64K:
> > +	default:	/* IMPDEF: treat any other value as 64k */
> > +		return 16;
> > +	}
> > +}
> > +
> > +static u64 tcr_tg_shift(struct kvm *kvm, u64 tcr, bool upper_range)
> > +{
> > +	unsigned int shift;
> > +
> > +	/* Someone was silly enough to encode TG0/TG1 differently */
> > +	if (upper_range)
> > +		shift = tg1_to_shift(FIELD_GET(TCR_EL1_TG1_MASK, tcr));
> > +	else
> > +		shift = tg0_to_shift(FIELD_GET(TCR_EL1_TG0_MASK, tcr));
> > +
> > +	return shift;
> > +}
> > +
> >  static int setup_s1_walk(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
> >  			 struct s1_walk_result *wr, u64 va)
> >  {
> > -	u64 hcr, sctlr, tcr, tg, ps, ia_bits, ttbr;
> > +	u64 hcr, sctlr, tcr, ps, ia_bits, ttbr;
> >  	unsigned int stride, x;
> > -	bool va55, tbi, lva;
> > +	bool va55, tbi, lva, upper_range;
> >  
> >  	va55 = va & BIT(55);
> > +	upper_range = va55 && wi->regime != TR_EL2;
> >  
> >  	if (vcpu_has_nv(vcpu)) {
> >  		hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
> > @@ -173,35 +213,12 @@ static int setup_s1_walk(struct kvm_vcpu *vcpu, struct s1_walk_info *wi,
> >  		BUG();
> >  	}
> >  
> > -	/* Someone was silly enough to encode TG0/TG1 differently */
> > -	if (va55 && wi->regime != TR_EL2) {
> > +	if (upper_range)
> >  		wi->txsz = FIELD_GET(TCR_T1SZ_MASK, tcr);
> > -		tg = FIELD_GET(TCR_TG1_MASK, tcr);
> > -
> > -		switch (tg << TCR_TG1_SHIFT) {
> > -		case TCR_TG1_4K:
> > -			wi->pgshift = 12;	 break;
> > -		case TCR_TG1_16K:
> > -			wi->pgshift = 14;	 break;
> > -		case TCR_TG1_64K:
> > -		default:	    /* IMPDEF: treat any other value as 64k */
> > -			wi->pgshift = 16;	 break;
> > -		}
> > -	} else {
> > +	else
> >  		wi->txsz = FIELD_GET(TCR_T0SZ_MASK, tcr);
> > -		tg = FIELD_GET(TCR_TG0_MASK, tcr);
> > -
> > -		switch (tg << TCR_TG0_SHIFT) {
> > -		case TCR_TG0_4K:
> > -			wi->pgshift = 12;	 break;
> > -		case TCR_TG0_16K:
> > -			wi->pgshift = 14;	 break;
> > -		case TCR_TG0_64K:
> > -		default:	    /* IMPDEF: treat any other value as 64k */
> > -			wi->pgshift = 16;	 break;
> > -		}
> > -	}
> >  
> > +	wi->pgshift = tcr_tg_shift(vcpu->kvm, tcr, upper_range);
> >  	wi->pa52bit = has_52bit_pa(vcpu, wi, tcr);
> >
> >  	ia_bits = get_ia_size(wi);
> > diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> > index 883b6c1008fb..2bfab3007cb3 100644
> > --- a/arch/arm64/kvm/nested.c
> > +++ b/arch/arm64/kvm/nested.c
> > @@ -378,20 +378,36 @@ static int walk_nested_s2_pgd(struct kvm_vcpu *vcpu, phys_addr_t ipa,
> >  	return 0;
> >  }
> >  
> > -static void vtcr_to_walk_info(u64 vtcr, struct s2_walk_info *wi)
> > +static unsigned int tg0_to_shift(u64 tg0)
> 
> Same comments as above.

Ack.

> 
> > +{
> > +	switch (tg0) {
> > +	case VTCR_EL2_TG0_4K:
> > +		return 12;
> > +	case VTCR_EL2_TG0_16K:
> > +		return 14;
> > +	case VTCR_EL2_TG0_64K:
> > +	default:	/* IMPDEF: treat any other value as 64k */
> > +		return 16;
> > +	}
> > +}
> > +
> > +static u64 vtcr_tg0_shift(struct kvm *kvm, u64 vtcr)
> > +{
> > +	u64 tg0 = FIELD_GET(VTCR_EL2_TG0_MASK, vtcr);
> > +	unsigned int shift = tg0_to_shift(tg0);
> > +
> > +	return shift;
> 
> shift is an unsigned int. Why is the return value a u64? Try and make
> sure that types are consistent, even if they cast nicely in C.

This is an error from me, I'll fix this.

> 
> > +}
> > +
> > +static size_t vtcr_tg0_size(struct kvm *kvm, u64 vtcr)
> > +{
> > +	return BIT(vtcr_tg0_shift(kvm, vtcr));
> > +}
> > +
> > +static void vtcr_to_walk_info(struct kvm *kvm, u64 vtcr, struct s2_walk_info *wi)
> 
> This prototype reads bizarrely. vtcr is per CPU, the walk info is
> evidently per CPU, and yet you pass a kvm struct.
> 
> Instead, rename this to:
> 
> static void setup_s2_walk(struct kvm_vcpu *vcpu,
> 			  struct s2_walk_info *wi)
> {
> 	u64 vtcr = vcpu_read_sys_reg(vcpu, VTCR_EL2);
> 
> and call that directly. You can then extract vcpu->kvm as needed. It
> also aligns the naming on the s1 part, which isn't a bad thing to do.

Agreed, makes sense.

> 
> >  {
> >  	wi->t0sz = vtcr & TCR_EL2_T0SZ_MASK;
> > -
> > -	switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
> > -	case VTCR_EL2_TG0_4K:
> > -		wi->pgshift = 12;	 break;
> > -	case VTCR_EL2_TG0_16K:
> > -		wi->pgshift = 14;	 break;
> > -	case VTCR_EL2_TG0_64K:
> > -	default:	    /* IMPDEF: treat any other value as 64k */
> > -		wi->pgshift = 16;	 break;
> > -	}
> > -
> > +	wi->pgshift = vtcr_tg0_shift(kvm, vtcr);
> >  	wi->sl = FIELD_GET(VTCR_EL2_SL0_MASK, vtcr);
> >  	/* Global limit for now, should eventually be per-VM */
> >  	wi->max_oa_bits = min(get_kvm_ipa_limit(),
> > @@ -414,7 +430,7 @@ int kvm_walk_nested_s2(struct kvm_vcpu *vcpu, phys_addr_t gipa,
> >  
> >  	wi.baddr = vcpu_read_sys_reg(vcpu, VTTBR_EL2);
> >  
> > -	vtcr_to_walk_info(vtcr, &wi);
> > +	vtcr_to_walk_info(vcpu->kvm, vtcr, &wi);
> >  
> >  	wi.be = vcpu_read_sys_reg(vcpu, SCTLR_EL2) & SCTLR_ELx_EE;
> >  
> > @@ -515,17 +531,19 @@ static u8 get_guest_mapping_ttl(struct kvm_s2_mmu *mmu, u64 addr)
> >  	u64 tmp, sz = 0, vtcr = mmu->tlb_vtcr;
> >  	kvm_pte_t pte;
> >  	u8 ttl, level;
> > +	struct kvm *kvm = kvm_s2_mmu_to_kvm(mmu);
> > +	size_t tg0_size = vtcr_tg0_size(kvm, vtcr);
> >  
> > -	lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(mmu)->mmu_lock);
> > +	lockdep_assert_held_write(&kvm->mmu_lock);
> >  
> > -	switch (FIELD_GET(VTCR_EL2_TG0_MASK, vtcr)) {
> > -	case VTCR_EL2_TG0_4K:
> > +	switch (tg0_size) {
> > +	case SZ_4K:
> >  		ttl = (TLBI_TTL_TG_4K << 2);
> >  		break;
> > -	case VTCR_EL2_TG0_16K:
> > +	case SZ_16K:
> >  		ttl = (TLBI_TTL_TG_16K << 2);
> >  		break;
> > -	case VTCR_EL2_TG0_64K:
> > +	case SZ_64K:
> 
> All these unit changes make the patch harder to read than it should
> be. Consider having a separate patch to do that.

Understood, sure.

Thanks for the feedback!
Wei-Lin Chang

> 
> Thanks,
> 
> 	M.
> 
> -- 
> Jazz isn't dead. It just smells funny.


^ permalink raw reply

* Re: [PATCH v10 16/20] coresight: Add PM callbacks for sink device
From: James Clark @ 2026-04-09 12:54 UTC (permalink / raw)
  To: Leo Yan
  Cc: coresight, linux-arm-kernel, Yeoreum Yun, Mark Rutland,
	Will Deacon, Yabin Cui, Keita Morisaki, Yuanfang Zhang,
	Greg Kroah-Hartman, Alexander Shishkin, Tamas Petz,
	Thomas Gleixner, Peter Zijlstra, Suzuki K Poulose, Mike Leach
In-Reply-To: <e7c6f497-f8f0-409b-b80a-a064b222c08d@linaro.org>



On 09/04/2026 11:52 am, James Clark wrote:
> 
> 
> On 05/04/2026 4:02 pm, Leo Yan wrote:
>> Unlike system level sinks, per-CPU sinks may lose power during CPU idle
>> states.  Currently, this applies specifically to TRBE.  This commit
>> invokes save and restore callbacks for the sink in the CPU PM notifier.
>>
>> If the sink provides PM callbacks but the source does not, this is
>> unsafe because the sink cannot be disabled safely unless the source
>> can also be controlled, so veto low power entry to avoid lockups.
>>
>> Tested-by: James Clark <james.clark@linaro.org>
>> Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
>> Reviewed-by: James Clark <james.clark@linaro.org>
>> Signed-off-by: Leo Yan <leo.yan@arm.com>
>> ---
>>   drivers/hwtracing/coresight/coresight-core.c | 46 ++++++++++++++++++ 
>> ++++++++--
>>   1 file changed, 43 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index 
>> c1e8debc76aba7eb5ecf7efe2a3b9b8b3e11b10c..a918bf6398a932de30fe9b4947020cc4c1cfb2f7 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -1736,14 +1736,15 @@ static void coresight_release_device_list(void)
>>   /* Return: 1 if PM is required, 0 if skip, <0 on error */
>>   static int coresight_pm_check(struct coresight_path *path)
>>   {
>> -    struct coresight_device *source;
>> -    bool source_has_cb;
>> +    struct coresight_device *source, *sink;
>> +    bool source_has_cb, sink_has_cb;
>>       if (!path)
>>           return 0;
>>       source = coresight_get_source(path);
>> -    if (!source)
>> +    sink = coresight_get_sink(path);
>> +    if (!source || !sink)
>>           return 0;
>>       /* Don't save and restore if the source is inactive */
>> @@ -1759,16 +1760,36 @@ static int coresight_pm_check(struct 
>> coresight_path *path)
>>       if (source_has_cb)
>>           return 1;
>> +    sink_has_cb = coresight_ops(sink)->pm_save_disable &&
>> +              coresight_ops(sink)->pm_restore_enable;
>> +    /*
>> +     * It is not permitted that the source has no callbacks while the 
>> sink
>> +     * does, as the sink cannot be disabled without disabling the 
>> source,
>> +     * which may lead to lockups. Alternatively, the ETM driver should
>> +     * enable self-hosted PM mode at probe (see etm4_probe()).
>> +     */
>> +    if (sink_has_cb) {
>> +        pr_warn_once("coresight PM failed: source has no PM callbacks; "
>> +                 "cannot safely control sink\n");
> 
> This prints out on my Orion board on a fresh boot because of how 
> pm_save_enable is setup there. Do we really need the configuration of 
> pm_save_enable for ETE/TRBE if we know that it always needs saving?
> 
> It also stops warning if I rmmod and modprobe the module after booting. 
> Seems like pm_save_enable is different depending on how the module is 
> loaded which doesn't seem right.
> 
>> +        return -EINVAL;
>> +    }
>> +
>>       return 0;
>>   }
>>   static int coresight_pm_device_save(struct coresight_device *csdev)
>>   {
>> +    if (!csdev || !coresight_ops(csdev)->pm_save_disable)
>> +        return 0;
>> +
>>       return coresight_ops(csdev)->pm_save_disable(csdev);
>>   }
>>   static void coresight_pm_device_restore(struct coresight_device *csdev)
>>   {
>> +    if (!csdev || !coresight_ops(csdev)->pm_restore_enable)
>> +        return;
>> +
>>       coresight_ops(csdev)->pm_restore_enable(csdev);
>>   }
>> @@ -1787,15 +1808,32 @@ static int coresight_pm_save(struct 
>> coresight_path *path)
>>       to = list_prev_entry(coresight_path_last_node(path), link);
>>       coresight_disable_path_from_to(path, from, to);
>> +    ret = coresight_pm_device_save(coresight_get_sink(path));
>> +    if (ret)
>> +        goto sink_failed;
>> +
> 
> The comment directly above this says "Up to the node before sink to 
> avoid latency". But then this line goes and saves the sink anyway. So 
> I'm not sure what's meant by the comment?
> 
>>       return 0;
>> +
>> +sink_failed:
>> +    if (!coresight_enable_path_from_to(path, coresight_get_mode(source),
>> +                       from, to))
>> +        coresight_pm_device_restore(source);
>> +
>> +    pr_err("Failed in coresight PM save on CPU%d: %d\n",
>> +           smp_processor_id(), ret);
>> +    this_cpu_write(percpu_pm_failed, true);
> 
> Why does only a failing sink set percpu_pm_failed when failing to save 
> the source exits early. Sashiko has a similar comment that this could 
> result in restoring uninitialised source save data later, but a comment 
> in this function about why the flow is like this would be helpful.
> 
> We have coresight_disable_path_from_to() which always succeeds and 
> doesn't return an error. TRBE is the only sink with a pm_save_disable()
> callback, but it always succeeds anyway.
> 
> Would it not be much simpler to require that sink save/restore callbacks 
> always succeed and don't return anything? Seems like this 
> percpu_pm_failed stuff is extra complexity for a scenario that doesn't 
> exist? The only thing that can fail is saving the source but it doesn't 
> goto sink_failed when that happens.
> 
> Ideally etm4_cpu_save() wouldn't have a return value either. It would be 
> good if we could find away to skip or ignore the timeouts in there 
> somehow because that's the only reason it can fail.
> 

etm4_disable_trace_unit() and etm4_enable_hw() also have timeouts but 
the timeouts only print warnings, they don't cause early exits or return 
error values.

Can we do the same for etm4_cpu_save()? It would be better to read and 
restore potentially 'unstable' register values than to early exit and 
restore known uninitialised values as it is here.

>> +    return ret;
>>   }
>>   static void coresight_pm_restore(struct coresight_path *path)
>>   {
>>       struct coresight_device *source = coresight_get_source(path);
>> +    struct coresight_device *sink = coresight_get_sink(path);
>>       struct coresight_node *from, *to;
>>       int ret;
>> +    coresight_pm_device_restore(sink);
>> +
>>       from = coresight_path_first_node(path);
>>       /* Up to the node before sink to avoid latency */
>>       to = list_prev_entry(coresight_path_last_node(path), link);
>> @@ -1808,6 +1846,8 @@ static void coresight_pm_restore(struct 
>> coresight_path *path)
>>       return;
>>   path_failed:
>> +    coresight_pm_device_save(sink);
>> +
>>       pr_err("Failed in coresight PM restore on CPU%d: %d\n",
>>              smp_processor_id(), ret);
>>
> 



^ permalink raw reply

* [PATCH] mm/arm: pgtable: remove young bit check for pte_valid_user
From: Brian Ruley @ 2026-04-09 12:54 UTC (permalink / raw)
  To: Russell King, Steve Capper, Will Deacon
  Cc: Brian Ruley, Russell King, linux-arm-kernel, linux-kernel

Fixes cache desync, which can cause undefined instruction,
translation and permission faults under heavy memory use.

This is an old bug introduced in commit 1971188aa196 ("ARM: 7985/1: mm:
implement pte_accessible for faulting mappings"), which included a check
for the young bit of a PTE. The underlying assumption was that old pages
are not cached, therefore, `__sync_icache_dcache' could be skipped
entirely.

However, under extreme memory pressure, page migrations happen
frequently and the assumption of uncached "old" pages does not hold.
Especially for systems that do not have swap, the migrated pages are
unequivocally marked old. This presents a problem, as it is possible
for the original page to be immediately mapped to another VA that
happens to share the same cache index in VIPT I-cache (we found this
bug on Cortex-A9). Without cache invalidation, the CPU will see the
old mapping whose physical page can now be used for a different
purpose, as illustrated below:

                Core                      Physical Memory
  +-------------------------------+     +------------------+
  | TLB                           |     |                  |
  |  VA_A 0xb6e6f -> pfn_q        |     | pfn_q: code      |
  +-------------------------------+     +------------------+
  | I-cache                       |
  |  set[VA_A bits] | tag=pfn_q   |
  +-------------------------------+

migrate (kcompactd):
  1. copy pfn_q --> pfn_r
  2. free pfn_q
  3. pte: VA_a -> pfn_r
  4. pte_mkold(pte) --> !young
  5. ICIALLUIS skipped (because !young)

pfn_src reused (OOM pressure):
  pte: VA_B -> pfn_q (different code)

bug:
                Core                      Physical Memory
  +-------------------------------+     +------------------+
  | TLB (empty)                   |     | pfn_r: old code  |
  +-------------------------------+     | pfn_q: new code  |
  | I-cache                       |     +------------------+
  |  set[VA_A bits] | tag=pfn_q   |<--- wrong instructions
  +-------------------------------+

This was verified on ba16-based board (i.MX6Quad/Dual, Cortex-A9) by
instrumenting the migration code to track recently migrated pages in a
ring buffer and then dumping them in the undefined instruction fault
handler. The bug can be triggered with `stress-ng':

  stress-ng --vm 4 --vm-bytes 2G --vm-method zero-one --verify

Note that the system we tested on has only 2G of memory, so the test
triggered the OOM-killer in our case.

Fixes: 1971188aa196 ("ARM: 7985/1: mm: implement pte_accessible for faulting mappings")
Signed-off-by: Brian Ruley <brian.ruley@gehealthcare.com>
---
 arch/arm/include/asm/pgtable.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 6fa9acd6a7f5..e3a5b4a9a65f 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -185,7 +185,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 #define pte_exec(pte)		(pte_isclear((pte), L_PTE_XN))
 
 #define pte_valid_user(pte)	\
-	(pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte))
+	(pte_valid(pte) && pte_isset((pte), L_PTE_USER))
 
 static inline bool pte_access_permitted(pte_t pte, bool write)
 {
-- 
2.47.3



^ permalink raw reply related

* Re: [PATCH 3/3] arm64: dts: broadcom: bcm2712: Add the otp nodes to firmware
From: Gregor Herburger @ 2026-04-09 13:03 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
	Ray Jui, Scott Branden, Broadcom internal kernel review list,
	Eric Anholt, Stefan Wahren, Srinivas Kandagatla, devicetree,
	linux-rpi-kernel, linux-arm-kernel, linux-kernel
In-Reply-To: <2aa66897-12ce-47c5-993d-e9e1d01a0cdd@kernel.org>

On Thu, Apr 09, 2026 at 02:15:32PM +0200, Krzysztof Kozlowski wrote:
> On 09/04/2026 14:02, Gregor Herburger wrote:
> > Hi Krzysztof,
> > 
> > thanks for reviewing.
> > 
> > On Thu, Apr 09, 2026 at 10:15:12AM +0200, Krzysztof Kozlowski wrote:
> >> On Wed, Apr 08, 2026 at 10:00:17AM +0200, Gregor Herburger wrote:
> >>> The Raspberry Pi 5 has two OTP registers (private and customer), add these
> >>> to the devicetree.
> >>
> >> So this sentence confirms my question on bindings - your device
> >> raspberrypi,bcm2835-firmware has these, thus you do not need these child
> >> nodes at all. Neither compatibles.
> > 
> > I dont't think so. In my understanding the bcm2835-firmware does not
> > provide the otp registers but only provides the interface to the
> > registers. Though I don't know the details how this is done but [1] says
> > that only BCM2712 has 512bits and the others (like bcm2711) have
> 
> Still the same. s/otp/interface/ so your device provides interface.
> 
Ok understood.

> > 256bits. So both devicetrees have the raspberrypi,bcm2835-firmware node
> > but only the bcm2712 has the raspberrypi,firmware-otp-private node while the 
> 
> Why does bcm2712 use bcm2835 compatible?

I have no idea. But it is like this.
> 
> Nodes and properties are not a solution. See DTS101 question - "...
> because my new device, which is compatible with an older one, does not
> support ..." and answer: No.
> 
> 
> 
> > raspberrypi,firmware-otp-customer is available in all raspberrys.
> > 
> >> Drop entire DTS and binding patches.
> > 
> > If I drop the binding patch how to distinguish the variants? Should I
> > add a SoC specific compatible? e.g. `raspberrypi,bcm2712-firmware` and
> > use it in the firmware/raspberrypi driver to add the second otp region?
> 
> So you have different devices/variants? What is the "variant" here?

Seems so. I suppose there is at least a bcm2712 variant and a non-bcm2712
variant (which is currently confusingly named 'raspberrypi,bcm2835-firmware').
> 
> Writing-bindings asks you to have per device compatible. Why standard
> rules do not apply here? (see also DTS101)

I am not arguing that the rules do not apply here. I want to find out
what is the correct way to do it. 

Should there then be a 'raspberrypi,bcm2712-firmware' compatible with
'raspberrypi,bcm2835-firmware' fallback?

> 
> > 
> > Also what I don't understand why we have all the bindings for
> 
> Neither do I.
Ok good. That is what confused me.

Best regards,
Gregor


^ permalink raw reply

* Re: [PATCH 3/3] arm64: dts: broadcom: bcm2712: Add the otp nodes to firmware
From: Krzysztof Kozlowski @ 2026-04-09 13:05 UTC (permalink / raw)
  To: Gregor Herburger
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
	Ray Jui, Scott Branden, Broadcom internal kernel review list,
	Eric Anholt, Stefan Wahren, Srinivas Kandagatla, devicetree,
	linux-rpi-kernel, linux-arm-kernel, linux-kernel
In-Reply-To: <adejoCVSpOW5wygD@gregor-framework>

On 09/04/2026 15:03, Gregor Herburger wrote:
>>>
>>> If I drop the binding patch how to distinguish the variants? Should I
>>> add a SoC specific compatible? e.g. `raspberrypi,bcm2712-firmware` and
>>> use it in the firmware/raspberrypi driver to add the second otp region?
>>
>> So you have different devices/variants? What is the "variant" here?
> 
> Seems so. I suppose there is at least a bcm2712 variant and a non-bcm2712
> variant (which is currently confusingly named 'raspberrypi,bcm2835-firmware').
>>
>> Writing-bindings asks you to have per device compatible. Why standard
>> rules do not apply here? (see also DTS101)
> 
> I am not arguing that the rules do not apply here. I want to find out
> what is the correct way to do it. 
> 
> Should there then be a 'raspberrypi,bcm2712-firmware' compatible with
> 'raspberrypi,bcm2835-firmware' fallback?

Yes, most likely. Let's wait a bit - maybe someone from Raspberry or
Broadcom will clarify things here.

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH RFC net-next 0/4] improve hw flow offload byte accounting
From: Daniel Golle @ 2026-04-09 13:07 UTC (permalink / raw)
  To: Felix Fietkau, John Crispin, Lorenzo Bianconi, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Simon Horman,
	Pablo Neira Ayuso, Florian Westphal, Phil Sutter, netdev,
	linux-kernel, linux-arm-kernel, linux-mediatek, netfilter-devel,
	coreteam

Hardware flow counters report raw byte counts whose semantics
vary by vendor -- some count ingress L2 frames, others egress
L2, others L3. The nf_flow_table framework currently passes
these bytes straight to conntrack without conversion, and
sub-interfaces (VLAN, PPPoE) that are bypassed by hw offload
never see any counter updates at all.

This series lets drivers declare what their counters represent,
so the framework can normalize to L3 for conntrack and
propagate per-layer stats to encap sub-interfaces.

Questions:
 - Sub-interface stats accesses vlan_dev_priv() directly --
   should there be a generic netdev callback instead?
 - Are there hw offload drivers whose counters do not fit the
   ingress-L2 / egress-L2 / L3 model?

Daniel Golle (4):
  net: flow_offload: let drivers report byte counter semantics
  nf_flow_table: track sub-interface and bridge ifindex in flow tuple
  nf_flow_table: convert hw byte counts and update sub-interface stats
  net: ethernet: mtk_eth_soc: report INGRESS_L2 byte_type in flow stats

 .../net/ethernet/mediatek/mtk_ppe_offload.c   |   1 +
 include/net/flow_offload.h                    |   7 +
 include/net/netfilter/nf_flow_table.h         |   5 +
 net/netfilter/nf_flow_table_core.c            |   2 +
 net/netfilter/nf_flow_table_offload.c         | 174 +++++++++++++++++-
 net/netfilter/nf_flow_table_path.c            |   8 +
 6 files changed, 195 insertions(+), 2 deletions(-)

-- 
2.53.0


^ permalink raw reply

* [PATCH RFC net-next 1/4] net: flow_offload: let drivers report byte counter semantics
From: Daniel Golle @ 2026-04-09 13:07 UTC (permalink / raw)
  To: Felix Fietkau, John Crispin, Lorenzo Bianconi, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Simon Horman,
	Pablo Neira Ayuso, Florian Westphal, Phil Sutter, netdev,
	linux-kernel, linux-arm-kernel, linux-mediatek, netfilter-devel,
	coreteam
In-Reply-To: <cover.1775739840.git.daniel@makrotopia.org>

Hardware flow offload engines count bytes at different points --
some report ingress L2 frame bytes, others egress L2, others L3.
Add an enum so drivers can declare what their counters represent.
The framework can then convert to L3 as needed for conntrack.

Default is FLOW_STATS_BYTES_L3 (zero), preserving existing
behaviour for all current drivers.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 include/net/flow_offload.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 70a02ee143080..7f5ef29b3abce 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -541,12 +541,19 @@ static inline bool flow_rule_match_has_control_flags(const struct flow_rule *rul
 	return flow_rule_has_control_flags(match.mask->flags, extack);
 }
 
+enum flow_stats_byte_type {
+	FLOW_STATS_BYTES_L3 = 0,	/* L3 (inner IP) bytes */
+	FLOW_STATS_BYTES_INGRESS_L2,	/* full ingress L2 frame bytes */
+	FLOW_STATS_BYTES_EGRESS_L2,	/* full egress L2 frame bytes */
+};
+
 struct flow_stats {
 	u64	pkts;
 	u64	bytes;
 	u64	drops;
 	u64	lastused;
 	enum flow_action_hw_stats used_hw_stats;
+	enum flow_stats_byte_type byte_type;
 	bool used_hw_stats_valid;
 };
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC net-next 2/4] nf_flow_table: track sub-interface and bridge ifindex in flow tuple
From: Daniel Golle @ 2026-04-09 13:07 UTC (permalink / raw)
  To: Felix Fietkau, John Crispin, Lorenzo Bianconi, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Simon Horman,
	Pablo Neira Ayuso, Florian Westphal, Phil Sutter, netdev,
	linux-kernel, linux-arm-kernel, linux-mediatek, netfilter-devel,
	coreteam
In-Reply-To: <cover.1775739840.git.daniel@makrotopia.org>

Store the net_device ifindex alongside each encap entry and for
bridge devices during path discovery so the flow offload stats
path can later update sub-interface (VLAN, PPPoE, bridge)
counters for hw-offloaded flows.

The indices are placed below __hash so they do not affect flow
tuple lookups.

No functional change -- the indices are stored but not yet used.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 include/net/netfilter/nf_flow_table.h | 5 +++++
 net/netfilter/nf_flow_table_core.c    | 2 ++
 net/netfilter/nf_flow_table_path.c    | 8 ++++++++
 3 files changed, 15 insertions(+)

diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index b09c11c048d51..ec1a18cfd9621 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -148,6 +148,9 @@ struct flow_offload_tuple {
 	/* All members above are keys for lookups, see flow_offload_hash(). */
 	struct { }			__hash;
 
+	int				encap_ifidx[NF_FLOW_TABLE_ENCAP_MAX];
+	int				bridge_ifidx;
+
 	u8				dir:2,
 					xmit_type:3,
 					encap_num:2,
@@ -221,11 +224,13 @@ struct nf_flow_route {
 			struct {
 				u16		id;
 				__be16		proto;
+				int		ifindex;
 			} encap[NF_FLOW_TABLE_ENCAP_MAX];
 			struct flow_offload_tunnel tun;
 			u8			num_encaps:2,
 						num_tuns:2,
 						ingress_vlans:2;
+			int			bridge_ifindex;
 		} in;
 		struct {
 			u32			ifindex;
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 2c4140e6f53c5..9bc8be177b392 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -115,6 +115,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
 	for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) {
 		flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id;
 		flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto;
+		flow_tuple->encap_ifidx[j] = route->tuple[dir].in.encap[i].ifindex;
 		if (route->tuple[dir].in.ingress_vlans & BIT(i))
 			flow_tuple->in_vlan_ingress |= BIT(j);
 		j++;
@@ -123,6 +124,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
 	flow_tuple->tun = route->tuple[dir].in.tun;
 	flow_tuple->encap_num = route->tuple[dir].in.num_encaps;
 	flow_tuple->tun_num = route->tuple[dir].in.num_tuns;
+	flow_tuple->bridge_ifidx = route->tuple[dir].in.bridge_ifindex;
 
 	switch (route->tuple[dir].xmit_type) {
 	case FLOW_OFFLOAD_XMIT_DIRECT:
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 6bb9579dcc2ab..c5817cb96a9f6 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -79,8 +79,10 @@ struct nft_forward_info {
 	struct id {
 		__u16	id;
 		__be16	proto;
+		int	ifindex;
 	} encap[NF_FLOW_TABLE_ENCAP_MAX];
 	u8 num_encaps;
+	int bridge_ifindex;
 	struct flow_offload_tunnel tun;
 	u8 num_tuns;
 	u8 ingress_vlans;
@@ -136,12 +138,15 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 					path->encap.id;
 				info->encap[info->num_encaps].proto =
 					path->encap.proto;
+				info->encap[info->num_encaps].ifindex =
+					path->dev->ifindex;
 				info->num_encaps++;
 			}
 			if (path->type == DEV_PATH_PPPOE)
 				memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN);
 			break;
 		case DEV_PATH_BRIDGE:
+			info->bridge_ifindex = path->dev->ifindex;
 			if (is_zero_ether_addr(info->h_source))
 				memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);
 
@@ -156,6 +161,7 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack,
 				}
 				info->encap[info->num_encaps].id = path->bridge.vlan_id;
 				info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
+				info->encap[info->num_encaps].ifindex = path->dev->ifindex;
 				info->num_encaps++;
 				break;
 			case DEV_PATH_BR_VLAN_UNTAG:
@@ -261,6 +267,7 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
 	for (i = 0; i < info.num_encaps; i++) {
 		route->tuple[!dir].in.encap[i].id = info.encap[i].id;
 		route->tuple[!dir].in.encap[i].proto = info.encap[i].proto;
+		route->tuple[!dir].in.encap[i].ifindex = info.encap[i].ifindex;
 	}
 
 	if (info.num_tuns &&
@@ -273,6 +280,7 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
 
 	route->tuple[!dir].in.num_encaps = info.num_encaps;
 	route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
+	route->tuple[!dir].in.bridge_ifindex = info.bridge_ifindex;
 
 	if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
 		memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC net-next 3/4] nf_flow_table: convert hw byte counts and update sub-interface stats
From: Daniel Golle @ 2026-04-09 13:07 UTC (permalink / raw)
  To: Felix Fietkau, John Crispin, Lorenzo Bianconi, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Simon Horman,
	Pablo Neira Ayuso, Florian Westphal, Phil Sutter, netdev,
	linux-kernel, linux-arm-kernel, linux-mediatek, netfilter-devel,
	coreteam
In-Reply-To: <cover.1775739840.git.daniel@makrotopia.org>

Hardware flow offload counters may report L2 frame bytes while
conntrack expects L3 (IP) bytes. When a driver sets byte_type
to INGRESS_L2 or EGRESS_L2, subtract the appropriate per-direction
encap and tunnel overhead to derive L3 byte counts for conntrack.

Additionally, propagate per-flow stats to bridge, VLAN and PPPoE
sub-interfaces that are bypassed by hardware offloading. Each
sub-interface gets the L3 byte count plus the overhead of any
inner encap layers below it, matching what the software path
would count. Both RX and TX directions are updated.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 net/netfilter/nf_flow_table_offload.c | 174 +++++++++++++++++++++++++-
 1 file changed, 172 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index 002ec15d988bd..67452da487c94 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -5,6 +5,8 @@
 #include <linux/netfilter.h>
 #include <linux/rhashtable.h>
 #include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/if_pppox.h>
 #include <linux/tc_act/tc_csum.h>
 #include <net/flow_offload.h>
 #include <net/ip_tunnels.h>
@@ -1008,10 +1010,135 @@ static void flow_offload_tuple_stats(struct flow_offload_work *offload,
 			      &offload->flowtable->flow_block.cb_list);
 }
 
+static int flow_offload_encap_hlen(const struct flow_offload_tuple *tuple,
+				   int idx)
+{
+	switch (tuple->encap[idx].proto) {
+	case htons(ETH_P_8021Q):
+	case htons(ETH_P_8021AD):
+		return VLAN_HLEN;
+	case htons(ETH_P_PPP_SES):
+		return PPPOE_SES_HLEN;
+	}
+	return 0;
+}
+
+static void flow_offload_encap_netstats(struct net_device *dev,
+					__be16 encap_proto,
+					bool rx, u64 pkts, u64 bytes)
+{
+	struct pcpu_sw_netstats *tstats;
+	struct vlan_pcpu_stats *vstats;
+
+	if (encap_proto == htons(ETH_P_8021Q) ||
+	    encap_proto == htons(ETH_P_8021AD)) {
+		vstats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats);
+		u64_stats_update_begin(&vstats->syncp);
+		if (rx) {
+			u64_stats_add(&vstats->rx_packets, pkts);
+			u64_stats_add(&vstats->rx_bytes, bytes);
+		} else {
+			u64_stats_add(&vstats->tx_packets, pkts);
+			u64_stats_add(&vstats->tx_bytes, bytes);
+		}
+		u64_stats_update_end(&vstats->syncp);
+	} else if (dev->tstats) {
+		tstats = this_cpu_ptr(dev->tstats);
+		u64_stats_update_begin(&tstats->syncp);
+		if (rx) {
+			u64_stats_add(&tstats->rx_packets, pkts);
+			u64_stats_add(&tstats->rx_bytes, bytes);
+		} else {
+			u64_stats_add(&tstats->tx_packets, pkts);
+			u64_stats_add(&tstats->tx_bytes, bytes);
+		}
+		u64_stats_update_end(&tstats->syncp);
+	}
+}
+
+/* Update sub-interface (VLAN, PPPoE) stats for hw-offloaded flows.
+ *
+ * The driver reports L3 (IP) bytes. Each sub-interface in the
+ * software path sees the frame with the headers of all layers
+ * BELOW it still present, so we add back inner-layer overhead.
+ *
+ * encap[] is ordered outermost to innermost, so walk from the
+ * innermost layer outward, accumulating overhead as we go.
+ */
+static void flow_offload_update_encap_stats(struct flow_offload *flow,
+					    struct flow_offload_tuple *tuple,
+					    bool rx, u64 pkts, u64 bytes)
+{
+	struct net_device *dev;
+	int inner_hlen = 0;
+	int i;
+
+	for (i = tuple->encap_num - 1; i >= 0; i--) {
+		if (tuple->in_vlan_ingress & BIT(i))
+			continue;
+
+		dev = dev_get_by_index_rcu(dev_net(flow->ct->ct_net),
+					   tuple->encap_ifidx[i]);
+		if (dev)
+			flow_offload_encap_netstats(dev,
+						    tuple->encap[i].proto, rx,
+						    pkts,
+						    bytes + inner_hlen * pkts);
+
+		inner_hlen += flow_offload_encap_hlen(tuple, i);
+	}
+
+	/* Bridge device sits outside all encap layers -- it sees
+	 * L3 bytes plus the full encap overhead.
+	 */
+	if (tuple->bridge_ifidx) {
+		dev = dev_get_by_index_rcu(dev_net(flow->ct->ct_net),
+					   tuple->bridge_ifidx);
+		if (dev && dev->tstats)
+			flow_offload_encap_netstats(dev, 0, rx, pkts,
+						    bytes + inner_hlen * pkts);
+	}
+}
+
+/* Compute per-direction input overhead from the encap and tunnel
+ * chains. Hardware flow counters report L2 frame bytes but
+ * conntrack expects L3 (inner IP) bytes -- matching what the
+ * software path sees after stripping all encap and tunnel headers.
+ */
+static int flow_offload_input_l2_overhead(struct flow_offload_tuple *tuple)
+{
+	int overhead = ETH_HLEN;
+	int i;
+
+	for (i = 0; i < tuple->encap_num; i++) {
+		if (tuple->in_vlan_ingress & BIT(i))
+			continue;
+
+		overhead += flow_offload_encap_hlen(tuple, i);
+	}
+
+	if (tuple->tun_num) {
+		switch (tuple->tun.l3_proto) {
+		case IPPROTO_IPIP:
+			overhead += sizeof(struct iphdr);
+			break;
+		case IPPROTO_IPV6:
+			overhead += sizeof(struct ipv6hdr);
+			break;
+		}
+	}
+
+	return overhead;
+}
+
 static void flow_offload_work_stats(struct flow_offload_work *offload)
 {
+	struct flow_offload_tuple *tuple;
 	struct flow_stats stats[FLOW_OFFLOAD_DIR_MAX] = {};
+	u64 l3_bytes[FLOW_OFFLOAD_DIR_MAX];
+	int l2_overhead;
 	u64 lastused;
+	int i;
 
 	flow_offload_tuple_stats(offload, FLOW_OFFLOAD_DIR_ORIGINAL, &stats[0]);
 	if (test_bit(NF_FLOW_HW_BIDIRECTIONAL, &offload->flow->flags))
@@ -1022,16 +1149,59 @@ static void flow_offload_work_stats(struct flow_offload_work *offload)
 	offload->flow->timeout = max_t(u64, offload->flow->timeout,
 				       lastused + flow_offload_get_timeout(offload->flow));
 
+	/* Convert hardware byte counts to L3 based on what the driver
+	 * reports.  Drivers that already report L3 (or do not set
+	 * byte_type) need no conversion.
+	 */
+	for (i = 0; i < FLOW_OFFLOAD_DIR_MAX; i++) {
+		l2_overhead = 0;
+
+		switch (stats[i].byte_type) {
+		case FLOW_STATS_BYTES_INGRESS_L2:
+			tuple = &offload->flow->tuplehash[i].tuple;
+			l2_overhead = flow_offload_input_l2_overhead(tuple);
+			break;
+		case FLOW_STATS_BYTES_EGRESS_L2:
+			tuple = &offload->flow->tuplehash[!i].tuple;
+			l2_overhead = flow_offload_input_l2_overhead(tuple);
+			break;
+		default:
+			break;
+		}
+		l3_bytes[i] = stats[i].bytes - stats[i].pkts * l2_overhead;
+	}
+
 	if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) {
 		if (stats[0].pkts)
 			nf_ct_acct_add(offload->flow->ct,
 				       FLOW_OFFLOAD_DIR_ORIGINAL,
-				       stats[0].pkts, stats[0].bytes);
+				       stats[0].pkts, l3_bytes[0]);
 		if (stats[1].pkts)
 			nf_ct_acct_add(offload->flow->ct,
 				       FLOW_OFFLOAD_DIR_REPLY,
-				       stats[1].pkts, stats[1].bytes);
+				       stats[1].pkts, l3_bytes[1]);
+	}
+
+	rcu_read_lock();
+	for (i = 0; i < FLOW_OFFLOAD_DIR_MAX; i++) {
+		tuple = &offload->flow->tuplehash[i].tuple;
+		if (!tuple->encap_num)
+			continue;
+
+		/* Input-side encap devices get RX stats */
+		if (stats[i].pkts)
+			flow_offload_update_encap_stats(offload->flow,
+							tuple, true,
+							stats[i].pkts,
+							l3_bytes[i]);
+		/* Same devices get TX stats from the other direction */
+		if (stats[!i].pkts)
+			flow_offload_update_encap_stats(offload->flow,
+							tuple, false,
+							stats[!i].pkts,
+							l3_bytes[!i]);
 	}
+	rcu_read_unlock();
 }
 
 static void flow_offload_work_handler(struct work_struct *work)
-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC net-next 4/4] net: ethernet: mtk_eth_soc: report INGRESS_L2 byte_type in flow stats
From: Daniel Golle @ 2026-04-09 13:07 UTC (permalink / raw)
  To: Felix Fietkau, John Crispin, Lorenzo Bianconi, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Matthias Brugger, AngeloGioacchino Del Regno, Simon Horman,
	Pablo Neira Ayuso, Florian Westphal, Phil Sutter, netdev,
	linux-kernel, linux-arm-kernel, linux-mediatek, netfilter-devel,
	coreteam
In-Reply-To: <cover.1775739840.git.daniel@makrotopia.org>

The MediaTek PPE MIB counters report ingress L2 frame bytes
including Ethernet, VLAN and PPPoE headers. Tell the flow offload
framework so it can derive correct L3 byte counts for conntrack
and update sub-interface counters.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
index cc8c4ef8038f3..68cb03a193f3f 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -557,6 +557,7 @@ mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
 				  &diff)) {
 		f->stats.pkts += diff.packets;
 		f->stats.bytes += diff.bytes;
+		f->stats.byte_type = FLOW_STATS_BYTES_INGRESS_L2;
 	}
 
 	return 0;
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH] arm64: dts: mediatek: mt7988a-bpi-r4pro: rename mgmt port to lan5
From: Frank Wunderlich @ 2026-04-09 13:09 UTC (permalink / raw)
  To: Frank Wunderlich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: devicetree, Daniel Golle, linux-kernel, linux-mediatek,
	Andrew LaMarche, linux-arm-kernel
In-Reply-To: <20260303202006.37515-1-linux@fw-web.de>

Hi,

just a friendly ping....

Am 3. März 2026 um 21:20 schrieb "Frank Wunderlich" <linux@fw-web.de mailto:linux@fw-web.de?to=%22Frank%20Wunderlich%22%20%3Clinux%40fw-web.de%3E >:
> 
> From: Frank Wunderlich <frank-w@public-files.de>
> 
> It turns out that the label mgmt confuses users and now official case is
> released where the port is labeled with number 5. So just rename it to
> lan5 to follow naming convension (lan1-4 from mxl switch and lan6 for lan-
> combo).
> 
> Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
> ---
>  arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
> index a48132f09411..1175ee156cb3 100644
> --- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
> @@ -207,7 +207,7 @@ &gsw_phy0_led0 {
>  };
>  
>  &gsw_port0 {
> - label = "mgmt";
> + label = "lan5";
>  };
>  
>  /* R4Pro has only port 0 connected, so disable the others */
> -- 
> 2.43.0
> 

regards Frank


^ permalink raw reply

* Re: [PATCH v2] media: cedrus: Fix failure to clean up hardware on probe failure
From: Paul Kocialkowski @ 2026-04-09 13:10 UTC (permalink / raw)
  To: Andrey Skvortsov
  Cc: Dan Carpenter, Maxime Ripard, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans Verkuil, linux-media, linux-staging, linux-arm-kernel,
	linux-sunxi, linux-kernel
In-Reply-To: <20260406221440.3721863-1-andrej.skvortzov@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2331 bytes --]

Hi,

On Tue 07 Apr 26, 01:14, Andrey Skvortsov wrote:
> From: Samuel Holland <samuel@sholland.org>
> 
> If V4L2 device fails to register, then SRAM still be claimed and as a
> result driver will not be able to probe again.
> 
>  cedrus 1c0e000.video-codec: Failed to claim SRAM
>  cedrus 1c0e000.video-codec: Failed to probe hardware
>  cedrus 1c0e000.video-codec: probe with driver cedrus failed with error -16
> 
> cedrus_hw_remove undoes everything that was previously done by
> cedrus_hw_probe, such as disabling runtime power management and
> releasing the claimed SRAM and reserved memory region.

Good catch, thanks for the patch!

Acked-by: Paul Kocialkowski <paulk@sys-base.io>

Note that I (still) plan to rework the architecture of this driver in the
future but such fixes are definitely welcome in the meantime.

All the best,

Paul

> Signed-off-by: Samuel Holland <samuel@sholland.org>
> Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
> Fixes: 50e761516f2b ("media: platform: Add Cedrus VPU decoder driver")
> ---
> 
> Changes in v2:
>  - remove duplicate 'in-body' From: record
>  - add more technical details to commit message
> 
>  drivers/staging/media/sunxi/cedrus/cedrus.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
> index 1d2130f35fffc..ee0e286add67d 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
> @@ -477,7 +477,7 @@ static int cedrus_probe(struct platform_device *pdev)
>  	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to register V4L2 device\n");
> -		return ret;
> +		goto err_hw;
>  	}
>  
>  	vfd = &dev->vfd;
> @@ -538,6 +538,8 @@ static int cedrus_probe(struct platform_device *pdev)
>  	v4l2_m2m_release(dev->m2m_dev);
>  err_v4l2:
>  	v4l2_device_unregister(&dev->v4l2_dev);
> +err_hw:
> +	cedrus_hw_remove(dev);
>  
>  	return ret;
>  }
> -- 
> 2.51.0
> 

-- 
Paul Kocialkowski,

Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/

Expert in multimedia, graphics and embedded hardware support with Linux.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v2] media: cedrus: Fix missing cleanup in error path
From: Paul Kocialkowski @ 2026-04-09 13:15 UTC (permalink / raw)
  To: Andrey Skvortsov
  Cc: Dan Carpenter, Maxime Ripard, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans Verkuil, linux-media, linux-staging, linux-arm-kernel,
	linux-sunxi, linux-kernel
In-Reply-To: <20260406221402.3721777-1-andrej.skvortzov@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1740 bytes --]

Hi,

On Tue 07 Apr 26, 01:14, Andrey Skvortsov wrote:
> From: Samuel Holland <samuel@sholland.org>
> 
> According to the documentation struct v4l2_fh has to be cleaned up with
> v4l2_fh_exit() before being freed. [1]
> Currently there is no actual bug here, when v4l2_fh_exit() isn't called.
> v4l2_fh_exit() in this case only destroys internal mutex. But it may
> change in the future, when v4l2_fh_init/v4l2_fh_exit will be enhanced.
> 
> 1. https://docs.kernel.org/driver-api/media/v4l2-fh.html

Good catch too, thanks!

Acked-by: Paul Kocialkowski <paulk@sys-base.io>

All the best,

Paul

> Signed-off-by: Samuel Holland <samuel@sholland.org>
> Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
> Fixes: 50e761516f2b ("media: platform: Add Cedrus VPU decoder driver")
> ---
> 
> Changes in v2:
>  - remove duplicate 'in-body' From: record
>  - add details to commit message
> 
> drivers/staging/media/sunxi/cedrus/cedrus.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
> index 6600245dff0e2..1d2130f35fffc 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
> @@ -391,6 +391,7 @@ static int cedrus_open(struct file *file)
>  err_m2m_release:
>  	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
>  err_free:
> +	v4l2_fh_exit(&ctx->fh);
>  	kfree(ctx);
>  	mutex_unlock(&dev->dev_mutex);
>  
> -- 
> 2.51.0
> 

-- 
Paul Kocialkowski,

Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/

Expert in multimedia, graphics and embedded hardware support with Linux.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v10 16/20] coresight: Add PM callbacks for sink device
From: Suzuki K Poulose @ 2026-04-09 13:14 UTC (permalink / raw)
  To: James Clark, Leo Yan
  Cc: coresight, linux-arm-kernel, Yeoreum Yun, Mark Rutland,
	Will Deacon, Yabin Cui, Keita Morisaki, Yuanfang Zhang,
	Greg Kroah-Hartman, Alexander Shishkin, Tamas Petz,
	Thomas Gleixner, Peter Zijlstra, Mike Leach
In-Reply-To: <e7c6f497-f8f0-409b-b80a-a064b222c08d@linaro.org>

On 09/04/2026 11:52, James Clark wrote:
> 
> 
> On 05/04/2026 4:02 pm, Leo Yan wrote:
>> Unlike system level sinks, per-CPU sinks may lose power during CPU idle
>> states.  Currently, this applies specifically to TRBE.  This commit
>> invokes save and restore callbacks for the sink in the CPU PM notifier.
>>
>> If the sink provides PM callbacks but the source does not, this is
>> unsafe because the sink cannot be disabled safely unless the source
>> can also be controlled, so veto low power entry to avoid lockups.
>>
>> Tested-by: James Clark <james.clark@linaro.org>
>> Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
>> Reviewed-by: James Clark <james.clark@linaro.org>
>> Signed-off-by: Leo Yan <leo.yan@arm.com>
>> ---
>>   drivers/hwtracing/coresight/coresight-core.c | 46 ++++++++++++++++++ 
>> ++++++++--
>>   1 file changed, 43 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/ 
>> hwtracing/coresight/coresight-core.c
>> index 
>> c1e8debc76aba7eb5ecf7efe2a3b9b8b3e11b10c..a918bf6398a932de30fe9b4947020cc4c1cfb2f7 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -1736,14 +1736,15 @@ static void coresight_release_device_list(void)
>>   /* Return: 1 if PM is required, 0 if skip, <0 on error */
>>   static int coresight_pm_check(struct coresight_path *path)
>>   {
>> -    struct coresight_device *source;
>> -    bool source_has_cb;
>> +    struct coresight_device *source, *sink;
>> +    bool source_has_cb, sink_has_cb;
>>       if (!path)
>>           return 0;
>>       source = coresight_get_source(path);
>> -    if (!source)
>> +    sink = coresight_get_sink(path);
>> +    if (!source || !sink)
>>           return 0;
>>       /* Don't save and restore if the source is inactive */
>> @@ -1759,16 +1760,36 @@ static int coresight_pm_check(struct 
>> coresight_path *path)
>>       if (source_has_cb)
>>           return 1;
>> +    sink_has_cb = coresight_ops(sink)->pm_save_disable &&
>> +              coresight_ops(sink)->pm_restore_enable;
>> +    /*
>> +     * It is not permitted that the source has no callbacks while the 
>> sink
>> +     * does, as the sink cannot be disabled without disabling the 
>> source,
>> +     * which may lead to lockups. Alternatively, the ETM driver should
>> +     * enable self-hosted PM mode at probe (see etm4_probe()).
>> +     */
>> +    if (sink_has_cb) {
>> +        pr_warn_once("coresight PM failed: source has no PM callbacks; "
>> +                 "cannot safely control sink\n");
> 
> This prints out on my Orion board on a fresh boot because of how 
> pm_save_enable is setup there. Do we really need the configuration of 
> pm_save_enable for ETE/TRBE if we know that it always needs saving?
> 
> It also stops warning if I rmmod and modprobe the module after booting. 
> Seems like pm_save_enable is different depending on how the module is 
> loaded which doesn't seem right.

Thats because the warning is pr_warn_*once*()

Suzuki


> 
>> +        return -EINVAL;
>> +    }
>> +
>>       return 0;
>>   }
>>   static int coresight_pm_device_save(struct coresight_device *csdev)
>>   {
>> +    if (!csdev || !coresight_ops(csdev)->pm_save_disable)
>> +        return 0;
>> +
>>       return coresight_ops(csdev)->pm_save_disable(csdev);
>>   }
>>   static void coresight_pm_device_restore(struct coresight_device *csdev)
>>   {
>> +    if (!csdev || !coresight_ops(csdev)->pm_restore_enable)
>> +        return;
>> +
>>       coresight_ops(csdev)->pm_restore_enable(csdev);
>>   }
>> @@ -1787,15 +1808,32 @@ static int coresight_pm_save(struct 
>> coresight_path *path)
>>       to = list_prev_entry(coresight_path_last_node(path), link);
>>       coresight_disable_path_from_to(path, from, to);
>> +    ret = coresight_pm_device_save(coresight_get_sink(path));
>> +    if (ret)
>> +        goto sink_failed;
>> +
> 
> The comment directly above this says "Up to the node before sink to 
> avoid latency". But then this line goes and saves the sink anyway. So 
> I'm not sure what's meant by the comment?
> 
>>       return 0;
>> +
>> +sink_failed:
>> +    if (!coresight_enable_path_from_to(path, coresight_get_mode(source),
>> +                       from, to))
>> +        coresight_pm_device_restore(source);
>> +
>> +    pr_err("Failed in coresight PM save on CPU%d: %d\n",
>> +           smp_processor_id(), ret);
>> +    this_cpu_write(percpu_pm_failed, true);
> 
> Why does only a failing sink set percpu_pm_failed when failing to save 
> the source exits early. Sashiko has a similar comment that this could 
> result in restoring uninitialised source save data later, but a comment 
> in this function about why the flow is like this would be helpful.
> 
> We have coresight_disable_path_from_to() which always succeeds and 
> doesn't return an error. TRBE is the only sink with a pm_save_disable()
> callback, but it always succeeds anyway.
> 
> Would it not be much simpler to require that sink save/restore callbacks 
> always succeed and don't return anything? Seems like this 
> percpu_pm_failed stuff is extra complexity for a scenario that doesn't 
> exist? The only thing that can fail is saving the source but it doesn't 
> goto sink_failed when that happens.
> 
> Ideally etm4_cpu_save() wouldn't have a return value either. It would be 
> good if we could find away to skip or ignore the timeouts in there 
> somehow because that's the only reason it can fail.
> 
>> +    return ret;
>>   }
>>   static void coresight_pm_restore(struct coresight_path *path)
>>   {
>>       struct coresight_device *source = coresight_get_source(path);
>> +    struct coresight_device *sink = coresight_get_sink(path);
>>       struct coresight_node *from, *to;
>>       int ret;
>> +    coresight_pm_device_restore(sink);
>> +
>>       from = coresight_path_first_node(path);
>>       /* Up to the node before sink to avoid latency */
>>       to = list_prev_entry(coresight_path_last_node(path), link);
>> @@ -1808,6 +1846,8 @@ static void coresight_pm_restore(struct 
>> coresight_path *path)
>>       return;
>>   path_failed:
>> +    coresight_pm_device_save(sink);
>> +
>>       pr_err("Failed in coresight PM restore on CPU%d: %d\n",
>>              smp_processor_id(), ret);
>>
> 



^ permalink raw reply

* [PATCH v1 1/3] arm64: dts: mediatek: mt7988a-bpi-r4pro: drop duplicate fan properties
From: Frank Wunderlich @ 2026-04-09 13:17 UTC (permalink / raw)
  To: Matthias Brugger, AngeloGioacchino Del Regno, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: Frank Wunderlich, linux-kernel, linux-arm-kernel, linux-mediatek,
	devicetree, Daniel Golle, Andrew LaMarche
In-Reply-To: <20260409131754.121737-1-linux@fw-web.de>

From: Frank Wunderlich <frank-w@public-files.de>

These properties are already set in the original node and do not need
to be defined again.

Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
---
 .../boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi     | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
index 1175ee156cb3..759f608d1081 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
@@ -185,13 +185,6 @@ &eth {
 	status = "okay";
 };
 
-&fan {
-	pinctrl-0 = <&pwm0_pins>;
-	pinctrl-names = "default";
-	pwms = <&pwm 0 50000>;
-	status = "okay";
-};
-
 &gmac0 {
 	status = "okay";
 };
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 3/3] arm64: dts: mediatek: mt7988a-bpi-r4pro: rework pcie gpio-hog handling
From: Frank Wunderlich @ 2026-04-09 13:17 UTC (permalink / raw)
  To: Matthias Brugger, AngeloGioacchino Del Regno, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: Frank Wunderlich, linux-kernel, linux-arm-kernel, linux-mediatek,
	devicetree, Daniel Golle, Andrew LaMarche
In-Reply-To: <20260409131754.121737-1-linux@fw-web.de>

From: Frank Wunderlich <frank-w@public-files.de>

The active-high property in base-dt cannot be overwritten and must be
set in separate overlay.

Fixes: f397471a6a8c ("arm64: dts: mediatek: mt7988: Add devicetree for BananaPi R4 Pro")
Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
---
 arch/arm64/boot/dts/mediatek/Makefile         |  8 ++++++++
 .../mt7988a-bananapi-bpi-r4-pro-cn13.dtso     | 20 +++++++++++++++++++
 .../mt7988a-bananapi-bpi-r4-pro-cn14.dtso     | 20 +++++++++++++++++++
 .../mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi |  2 --
 4 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn13.dtso
 create mode 100644 arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn14.dtso

diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 387faa9c2a09..a86fb313b1a9 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -47,6 +47,8 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-2g5.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-emmc.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-4e.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-cn13.dtbo
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-cn14.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-cn15.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-cn18.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-emmc.dtbo
@@ -70,18 +72,24 @@ mt7988a-bananapi-bpi-r4-2g5-sd-dtbs := \
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-2g5-sd.dtb
 mt7988a-bananapi-bpi-r4-pro-8x-emmc-dtbs := \
 	mt7988a-bananapi-bpi-r4-pro-8x.dtb \
+	mt7988a-bananapi-bpi-r4-pro-cn13.dtbo \
+	mt7988a-bananapi-bpi-r4-pro-cn14.dtbo \
 	mt7988a-bananapi-bpi-r4-pro-emmc.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-emmc.dtb
 mt7988a-bananapi-bpi-r4-pro-8x-sd-dtbs := \
 	mt7988a-bananapi-bpi-r4-pro-8x.dtb \
+	mt7988a-bananapi-bpi-r4-pro-cn13.dtbo \
+	mt7988a-bananapi-bpi-r4-pro-cn14.dtbo \
 	mt7988a-bananapi-bpi-r4-pro-sd.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-sd.dtb
 mt7988a-bananapi-bpi-r4-pro-8x-sd-cn15-dtbs := \
 	mt7988a-bananapi-bpi-r4-pro-8x-sd.dtb \
+	mt7988a-bananapi-bpi-r4-pro-cn14.dtbo \
 	mt7988a-bananapi-bpi-r4-pro-cn15.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-sd-cn15.dtb
 mt7988a-bananapi-bpi-r4-pro-8x-sd-cn18-dtbs := \
 	mt7988a-bananapi-bpi-r4-pro-8x-sd.dtb \
+	mt7988a-bananapi-bpi-r4-pro-cn13.dtbo \
 	mt7988a-bananapi-bpi-r4-pro-cn18.dtbo
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-pro-8x-sd-cn18.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn13.dtso b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn13.dtso
new file mode 100644
index 000000000000..973b76ba0cbf
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn13.dtso
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 MediaTek Inc.
+ * Author: Frank Wunderlich <frank-w@public-files.de>
+ */
+
+/* This enables key-m slot CN13 on pcie2(11280000 1L0) on BPI-R4-Pro */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	compatible = "bananapi,bpi-r4-pro", "mediatek,mt7988a";
+};
+
+&{/soc/pinctrl@1001f000/pcie-2-hog} {
+	output-high;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn14.dtso b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn14.dtso
new file mode 100644
index 000000000000..90b2a64459c3
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn14.dtso
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2025 MediaTek Inc.
+ * Author: Frank Wunderlich <frank-w@public-files.de>
+ */
+
+/* This enables key-m slot CN14 on pcie3(11290000 1L1) on BPI-R4-Pro */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	compatible = "bananapi,bpi-r4-pro", "mediatek,mt7988a";
+};
+
+&{/soc/pinctrl@1001f000/pcie-3-hog} {
+	output-high;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
index 7f770a76775a..5c5d4e26aa56 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
@@ -432,14 +432,12 @@ mux {
 	pcie-2-hog {
 		gpio-hog;
 		gpios = <79 GPIO_ACTIVE_HIGH>;
-		output-high;
 	};
 
 	/* 1L1 0=key-b (CN18), 1=key-m (CN14) */
 	pcie-3-hog {
 		gpio-hog;
 		gpios = <63 GPIO_ACTIVE_HIGH>;
-		output-high;
 	};
 
 	pwm0_pins: pwm0-pins {
-- 
2.43.0



^ permalink raw reply related

* [PATCH v1 0/3] some BPI-R4Pro dts updates
From: Frank Wunderlich @ 2026-04-09 13:17 UTC (permalink / raw)
  To: Matthias Brugger, AngeloGioacchino Del Regno, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: Frank Wunderlich, linux-kernel, linux-arm-kernel, linux-mediatek,
	devicetree, Daniel Golle, Andrew LaMarche

From: Frank Wunderlich <frank-w@public-files.de>

There are some parts of BPI-R4Pro DTS that need to be changed. Currently
there should be not much users of the mainline-dts and we noticed some
things while openwrt integration.

Frank Wunderlich (3):
  arm64: dts: mediatek: mt7988a-bpi-r4pro: drop duplicate fan properties
  arm64: dts: mediatek: mt7988a-bpi-r4pro: update gpio-leds
  arm64: dts: mediatek: mt7988a-bpi-r4pro: rework pcie gpio-hog handling

 arch/arm64/boot/dts/mediatek/Makefile         |  8 ++++++++
 .../mt7988a-bananapi-bpi-r4-pro-cn13.dtso     | 20 +++++++++++++++++++
 .../mt7988a-bananapi-bpi-r4-pro-cn14.dtso     | 20 +++++++++++++++++++
 .../mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi | 15 ++++----------
 4 files changed, 52 insertions(+), 11 deletions(-)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn13.dtso
 create mode 100644 arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro-cn14.dtso

-- 
2.43.0



^ permalink raw reply

* [PATCH v1 2/3] arm64: dts: mediatek: mt7988a-bpi-r4pro: update gpio-leds
From: Frank Wunderlich @ 2026-04-09 13:17 UTC (permalink / raw)
  To: Matthias Brugger, AngeloGioacchino Del Regno, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: Frank Wunderlich, linux-kernel, linux-arm-kernel, linux-mediatek,
	devicetree, Daniel Golle, Andrew LaMarche
In-Reply-To: <20260409131754.121737-1-linux@fw-web.de>

From: Frank Wunderlich <frank-w@public-files.de>

On the official case the red LED is named ERR, the blue LED is named ACT.​​​​​​​​​​​​​​​​
Reflect these labels in function and set them default off.

Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
---
 .../boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi      | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
index 759f608d1081..7f770a76775a 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-pro.dtsi
@@ -61,14 +61,16 @@ gpio-leds {
 
 		led_red: sys-led-red {
 			color = <LED_COLOR_ID_RED>;
+			function = LED_FUNCTION_FAULT;
 			gpios = <&pca9555 15 GPIO_ACTIVE_HIGH>;
-			default-state = "on";
+			default-state = "off";
 		};
 
 		led_blue: sys-led-blue {
 			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_ACTIVITY;
 			gpios = <&pca9555 14 GPIO_ACTIVE_HIGH>;
-			default-state = "on";
+			default-state = "off";
 		};
 	};
 
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH v1] phy: rockchip-snps-pcie3:phy: Configure clkreq_n and PowerDown for all lanes
From: Anand Moon @ 2026-04-09 13:30 UTC (permalink / raw)
  To: Niklas Cassel
  Cc: Shawn Lin, Vinod Koul, Neil Armstrong, Heiko Stuebner,
	open list:GENERIC PHY FRAMEWORK,
	moderated list:ARM/Rockchip SoC support,
	open list:ARM/Rockchip SoC support, open list
In-Reply-To: <add2QFfHd5Jv9XU7@fedora>

Hi Niklas,

Thanks for your review comments.

On Thu, 9 Apr 2026 at 15:19, Niklas Cassel <cassel@kernel.org> wrote:
>
> +Shawn
>
> Hello Anand,
>
> On Thu, Apr 09, 2026 at 10:19:30AM +0530, Anand Moon wrote:
> > During the rk3588_p3phy_init sequence, the driver now explicitly
>
> Please use imperative mood, active voice.
>
>
> > configures each lane's CON0 register to ensure
> > - PIPE 4.3 Compliance: clkreq_n (bit 6) is forced low (asserted) to meet
> >   sideband signal requirements.
> > - Active Power State: PowerDown[3:0] (bits 11:8) is set to P0
> >   (Normal Operational State) to ensure the PHY is fully powered and ready
> >   for link training.
> >
> > These changes ensure that all lanes are consistently transitioned from
> > reset into a known-good operational state, preventing undefined behavior
> > and ensuring the PHY is ready for high-speed data transmission.
>
Ok, I will update this.I f
> First describe the problem, then describe how you fix it.
I was investigating the PCIE30X4_CLKREQn issue highlighted by Shawn Lin,
analyzing the RK3588 TRM clock request configurations (page 878)

[1] https://lore.kernel.org/all/77f0d3c2-649f-770d-1636-6fd52f3b5f5e@rock-chips.com/

Looking into the power management state on Intel’s PCI Express Power Management
documentation, which defines states such as P0, P0s, P1, P1.1, P1.2, and P2
Understanding this mapping is for interpreting the behavior of lane-specific
clock requests, so initialize this to the P0 state..

[2] https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/phy-interface-pci-express-sata-usb30-architectures-3.1.pdf
>
>
> Kind regards,
> Niklas

Thanks
-Anand


^ permalink raw reply


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