* [PATCH v4 2/3] arm64: dts: freescale: add Aquila iMX95 support
From: Franz Schnyder @ 2026-05-21 17:11 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, linux-kernel, imx, linux-arm-kernel,
Francesco Dolcini, Franz Schnyder, João Paulo Gonçalves,
Emanuele Ghidoli, Francesco Dolcini, Antoine Gouby,
Ernest Van Hoecke
In-Reply-To: <20260521-add-aquila-imx95-v4-0-5a7f86c824f5@toradex.com>
From: João Paulo Gonçalves <joao.goncalves@toradex.com>
Add support for the Toradex Aquila iMX95 and its development carrier
board.
The module consists of an NXP i.MX95 family SoC, up to 16GB LPDDR5 RAM,
up to 128GB of storage, a USB 3.2 OTG and USB 2.0 Host, a Gigabit
Ethernet PHY, a 10 Gigabit Ethernet interface, an I2C EEPROM and
Temperature Sensor, an RX8130 RTC, one Quad lane CSI interface, one Quad
lane DSI or CSI interface, one LVDS interface (one or two channels), and
some optional addons: DisplayPort (through a DSI-DP bridge), TPM 2.0,
and a WiFi/BT module.
Link: https://www.toradex.com/computer-on-modules/aquila-arm-family/nxp-imx95
Link: https://www.toradex.com/products/carrier-board/aquila-development-board-kit
Signed-off-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
Co-developed-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
Co-developed-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Co-developed-by: Antoine Gouby <antoine.gouby@toradex.com>
Signed-off-by: Antoine Gouby <antoine.gouby@toradex.com>
Co-developed-by: Ernest Van Hoecke <ernest.vanhoecke@toradex.com>
Signed-off-by: Ernest Van Hoecke <ernest.vanhoecke@toradex.com>
Co-developed-by: Franz Schnyder <franz.schnyder@toradex.com>
Signed-off-by: Franz Schnyder <franz.schnyder@toradex.com>
---
v4: Removed som_dsi2dp_bridge node from the dev board
since SoC's DSI controller is unsupported
v3: -Changed QSPI_1 4bit iomux node name to 'flexspi14bitgrp'
-Deleted the cdns,* properties from flexspi1
v2: -Reordered iomux alphanumerically by node name
-Changed Francesco's tags to have the Toradex mail address
v1: https://lore.kernel.org/all/20260506-add-aquila-imx95-v1-2-69c8ee1c5413@toradex.com/
---
arch/arm64/boot/dts/freescale/Makefile | 1 +
arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts | 389 +++++++
arch/arm64/boot/dts/freescale/imx95-aquila.dtsi | 1160 ++++++++++++++++++++
3 files changed, 1550 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 513f61eb27b85..c8697b6ae01c5 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -523,6 +523,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-frdm.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-sof.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-dev.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-toradex-smarc-dev.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596sa-mb-smarc-2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-var-dart-sonata.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts b/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts
new file mode 100644
index 0000000000000..3df17700b632f
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) Toradex
+ *
+ * https://www.toradex.com/computer-on-modules/aquila-arm-family/nxp-imx95
+ * https://www.toradex.com/products/carrier-board/aquila-development-board-kit
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/usb/pd.h>
+#include "imx95-aquila.dtsi"
+
+/ {
+ model = "Aquila iMX95 on Aquila Development Board";
+ compatible = "toradex,aquila-imx95-dev",
+ "toradex,aquila-imx95",
+ "fsl,imx95";
+
+ aliases {
+ eeprom1 = &carrier_eeprom;
+ };
+
+ dp_1_connector: dp0-connector {
+ compatible = "dp-connector";
+ dp-pwr-supply = <®_dp_3p3v>;
+ type = "full-size";
+
+ port {
+ dp_1_connector_in: endpoint {
+ remote-endpoint = <&dsi2dp_out>;
+ };
+ };
+ };
+
+ reg_carrier_1p8v: regulator-carrier-1p8v {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-name = "On-carrier 1V8";
+ };
+
+ reg_dp_3p3v: regulator-dp-3p3v {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_21_dp>;
+ /* Aquila GPIO_21_DP */
+ gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "DP_3V3";
+ startup-delay-us = <10000>;
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,bitclock-master = <&codec_dai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&codec_dai>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,name = "aquila-wm8904";
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "IN2L", "Line In Jack",
+ "IN2R", "Line In Jack",
+ "Microphone Jack", "MICBIAS",
+ "IN1L", "Microphone Jack",
+ "IN1R", "Digital Mic";
+ simple-audio-card,widgets =
+ "Microphone", "Microphone Jack",
+ "Microphone", "Digital Mic",
+ "Headphone", "Headphone Jack",
+ "Line", "Line In Jack";
+
+ codec_dai: simple-audio-card,codec {
+ sound-dai = <&wm8904_1a>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai2>;
+ };
+ };
+};
+
+/* Aquila ADC_[1-4] */
+&adc1 {
+ status = "okay";
+};
+
+/* Aquila CTRL_WAKE1_MICO# */
+&aquila_key_wake {
+ status = "okay";
+};
+
+&dsi2dp_out {
+ remote-endpoint = <&dp_1_connector_in>;
+};
+
+/* Aquila ETH_1 */
+&enetc_port0 {
+ status = "okay";
+};
+
+/* Aquila CAN_1 */
+&flexcan1 {
+ status = "okay";
+};
+
+/* Aquila CAN_2 */
+&flexcan2 {
+ status = "okay";
+};
+
+/* Aquila CAN_3 */
+&flexcan3 {
+ status = "okay";
+};
+
+/* Aquila CAN_4 */
+&flexcan4 {
+ status = "okay";
+};
+
+/* Aquila QSPI_1 */
+&flexspi1 {
+ pinctrl-0 = <&pinctrl_flexspi1_4bit>,
+ <&pinctrl_qspi_cs1>;
+
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <66000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ };
+};
+
+&gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_8>;
+};
+
+&gpio4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_1>,
+ <&pinctrl_gpio_2>,
+ <&pinctrl_gpio_3>,
+ <&pinctrl_gpio_4>,
+ <&pinctrl_gpio_5>,
+ <&pinctrl_gpio_6>,
+ <&pinctrl_gpio_7>;
+};
+
+/* Aquila I2C_1 */
+&lpi2c2 {
+ status = "okay";
+
+ fan_controller: fan@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ #pwm-cells = <2>;
+
+ fan {
+ cooling-levels = <255>;
+ pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>;
+ };
+ };
+
+ wm8904_1a: audio-codec@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2_mclk>;
+ clocks = <&scmi_clk IMX95_CLK_SAI2>;
+ clock-names = "mclk";
+ #sound-dai-cells = <0>;
+ AVDD-supply = <®_carrier_1p8v>;
+ CPVDD-supply = <®_carrier_1p8v>;
+ DBVDD-supply = <®_carrier_1p8v>;
+ DCVDD-supply = <®_carrier_1p8v>;
+ MICVDD-supply = <®_carrier_1p8v>;
+ wlf,drc-cfg-names = "default", "peaklimiter";
+ /*
+ * Config registers per name, respectively:
+ * KNEE_IP = 0, KNEE_OP = 0, HI_COMP = 1, LO_COMP = 1
+ * KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1
+ */
+ wlf,drc-cfg-regs = /bits/ 16 <0x01af 0x3248 0x0000 0x0000>,
+ /bits/ 16 <0x04af 0x324b 0x0010 0x0408>;
+ /* GPIO1 = DMIC_CLK, don't touch others */
+ wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>;
+ wlf,in1r-as-dmicdat2;
+ };
+
+ /* Current measurement into module VCC */
+ hwmon@41 {
+ compatible = "ti,ina226";
+ reg = <0x41>;
+ shunt-resistor = <5000>;
+ };
+
+ temperature-sensor@4f {
+ compatible = "ti,tmp1075";
+ reg = <0x4f>;
+ };
+
+ /* USB-C OTG (TCPC USB PD PHY) */
+ tcpc@52 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x52>;
+ interrupt-parent = <&som_gpio_expander_1>;
+ interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+
+ connector {
+ compatible = "usb-c-connector";
+ data-role = "dual";
+ op-sink-microwatt = <0>;
+ power-role = "dual";
+ self-powered;
+ sink-pdos = <PDO_FIXED(5000, 0, PDO_FIXED_USB_COMM)>;
+ source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ try-power-role = "sink";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ typec_con_hs: endpoint {
+ remote-endpoint = <&usb1_con_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ typec_con_ss: endpoint {
+ remote-endpoint = <&usb1_con_ss>;
+ };
+ };
+ };
+ };
+ };
+
+ carrier_eeprom: eeprom@57 {
+ compatible = "st,24c02", "atmel,24c02";
+ reg = <0x57>;
+ pagesize = <16>;
+ };
+};
+
+/* Aquila I2C_2 */
+&i3c2 {
+ status = "okay";
+};
+
+/* Aquila I2C_4_CSI1 */
+&lpi2c4 {
+ status = "okay";
+};
+
+/* Aquila I2C_6 */
+&lpi2c5 {
+ status = "okay";
+};
+
+/* Aquila I2C_3_DSI1/I2C_5_CSI2 */
+&lpi2c8 {
+ status = "okay";
+
+ i2c-mux@70 {
+ compatible = "nxp,pca9543";
+ reg = <0x70>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* I2C on DSI Connector Pin #4 and #6 */
+ i2c_dsi_0: i2c@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ /* I2C on DSI Connector Pin #52 and #54 */
+ i2c_dsi_1: i2c@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+/* Aquila SPI_1 */
+&lpspi6 {
+ status = "okay";
+};
+
+/* Aquila UART_3, used as the Linux Console */
+&lpuart1 {
+ status = "okay";
+};
+
+/* Aquila UART_4 */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Aquila UART_1 */
+&lpuart3 {
+ status = "okay";
+};
+
+/* Aquila UART_2 as RS485 */
+&lpuart7 {
+ linux,rs485-enabled-at-boot-time;
+ rs485-rts-active-low;
+ rs485-rx-during-tx;
+
+ status = "okay";
+};
+
+/* Aquila PCIE_1 */
+&pcie0 {
+ status = "okay";
+};
+
+/* Aquila I2S_1 */
+&sai2 {
+ status = "okay";
+};
+
+/* Aquila PWM_1 */
+&tpm3 {
+ status = "okay";
+};
+
+/* Aquila PWM_2 */
+&tpm6 {
+ status = "okay";
+};
+
+/* Aquila PWM_3_DSI and PWM_4_DP */
+&tpm5 {
+ status = "okay";
+};
+
+/* Aquila USB_2, optional Bluetooth USB */
+&usb2 {
+ status = "okay";
+};
+
+/* Aquila USB_1 */
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ status = "okay";
+
+ port {
+ usb1_con_hs: endpoint {
+ remote-endpoint = <&typec_con_hs>;
+ };
+ };
+};
+
+&usb3_phy {
+ orientation-switch;
+
+ status = "okay";
+
+ port {
+ usb1_con_ss: endpoint {
+ remote-endpoint = <&typec_con_ss>;
+ };
+ };
+};
+
+/* Aquila SD_1 */
+&usdhc2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi b/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi
new file mode 100644
index 0000000000000..69dc962a24a1d
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi
@@ -0,0 +1,1160 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) Toradex
+ *
+ * https://www.toradex.com/computer-on-modules/aquila-arm-family/nxp-imx95
+ */
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include "imx95.dtsi"
+
+/ {
+ aliases {
+ can0 = &flexcan1;
+ can1 = &flexcan2;
+ can2 = &flexcan3;
+ can3 = &flexcan4;
+ eeprom0 = &som_eeprom;
+ ethernet0 = &enetc_port0;
+ i2c0 = &lpi2c3;
+ i2c1 = &lpi2c2;
+ i2c2 = &i3c2;
+ i2c3 = &lpi2c8;
+ i2c4 = &lpi2c4;
+ i2c6 = &lpi2c5;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ rtc0 = &rtc_i2c;
+ rtc1 = &scmi_bbm;
+ serial0 = &lpuart3;
+ serial1 = &lpuart7;
+ serial2 = &lpuart1;
+ serial3 = &lpuart2;
+ usb0 = &usb3;
+ usb1 = &usb2;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ aquila_key_wake: gpio-key-wakeup {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ctrl_wake1_mico>;
+
+ status = "disabled";
+
+ key-wakeup {
+ /* Aquila CTRL_WAKE1_MICO# */
+ gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+ label = "Wake Up";
+ wakeup-source;
+ linux,code = <KEY_WAKEUP>;
+ };
+ };
+
+ clk_dsi2dp_refclk: clock-dsi2dp-refclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <27000000>;
+ };
+
+ clk_dsi2dp_refclk_en: clock-dsi2dp-refclk-en {
+ compatible = "gpio-gate-clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ctrl_dp_clk_en>;
+ clocks = <&clk_dsi2dp_refclk>;
+ #clock-cells = <0>;
+ /* CTRL_DP_CLK_EN */
+ enable-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ clk_serdes_eth_ref: clock-serdes-eth-ref {
+ compatible = "gpio-gate-clock";
+ #clock-cells = <0>;
+ /* CTRL_ETH_REF_CLK_STBY */
+ enable-gpios = <&som_gpio_expander_0 6 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-max-microvolt = <1800000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-name = "On-module +V1.8";
+ };
+
+ reg_dp_1p2v: regulator-dp-1p2v {
+ compatible = "regulator-fixed";
+ /* CTRL_DP_BRIDGE_EN */
+ gpios = <&som_gpio_expander_0 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-max-microvolt = <1200000>;
+ regulator-min-microvolt = <1200000>;
+ regulator-name = "On-module +V1.2_DP";
+ vin-supply = <®_1p8v>;
+ };
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ /* Aquila USB_1_EN */
+ gpios = <&som_gpio_expander_0 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-name = "USB_1_EN";
+ };
+
+ reg_usb2_vbus: regulator-usb2-vbus {
+ compatible = "regulator-fixed";
+ /* Aquila USB_2_EN */
+ gpios = <&som_gpio_expander_0 3 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-name = "USB_2_H_EN";
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sd1_pwr_en>;
+ /* Aquila SD_1_PWR_EN */
+ gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ off-on-delay-us = <100000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "SD_1_PWR_EN";
+ startup-delay-us = <20000>;
+ };
+
+ reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc {
+ compatible = "regulator-gpio";
+ /* PMIC_SD_1_VSEL */
+ gpios = <&som_gpio_expander_1 9 GPIO_ACTIVE_HIGH>;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <1800000>;
+ regulator-name = "PMIC_SD_1_VSEL";
+ states = <1800000 0x1>,
+ <3300000 0x0>;
+ };
+
+ remoteproc-cm7 {
+ compatible = "fsl,imx95-cm7";
+ mboxes = <&mu7 0 1 &mu7 1 1 &mu7 3 1>;
+ mbox-names = "tx", "rx", "rxdb";
+ memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>,
+ <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>, <&m7_reserved>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ linux_cma: linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x3c000000>;
+ alloc-ranges = <0 0x80000000 0 0x7f000000>;
+ linux,cma-default;
+ };
+
+ m7_reserved: memory@80000000 {
+ reg = <0 0x80000000 0 0x1000000>;
+ no-map;
+ };
+
+ rsc_table: rsc-table@88220000 {
+ reg = <0 0x88220000 0 0x1000>;
+ no-map;
+ };
+
+ vdev0vring0: vdev0vring0@88000000 {
+ reg = <0 0x88000000 0 0x8000>;
+ no-map;
+ };
+
+ vdev0vring1: vdev0vring1@88008000 {
+ reg = <0 0x88008000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring0: vdev1vring0@88010000 {
+ reg = <0 0x88010000 0 0x8000>;
+ no-map;
+ };
+
+ vdev1vring1: vdev1vring1@88018000 {
+ reg = <0 0x88018000 0 0x8000>;
+ no-map;
+ };
+
+ vdevbuffer: vdevbuffer@88020000 {
+ compatible = "shared-dma-pool";
+ reg = <0 0x88020000 0 0x100000>;
+ no-map;
+ };
+ };
+};
+
+/* Aquila ADC_[1-4] */
+&adc1 {
+ vref-supply = <®_1p8v>;
+};
+
+/* Aquila ETH_1 */
+&enetc_port0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enetc0>;
+ phy-handle = <ðphy1>;
+ phy-mode = "rgmii-id";
+};
+
+/* Aquila CAN_1 */
+&flexcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+};
+
+/* Aquila CAN_2 */
+&flexcan2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+};
+
+/* Aquila CAN_3 */
+&flexcan3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan3>;
+};
+
+/* Aquila CAN_4 */
+&flexcan4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan4>;
+};
+
+/* Aquila QSPI_1 */
+&flexspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexspi1_8bit>,
+ <&pinctrl_qspi_cs1>;
+};
+
+&gpio1 {
+ gpio-line-names = "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AQUILA_C24", /* 10 */
+ "",
+ "AQUILA_B17",
+ "CTRL_GPIO_EXP_INT#",
+ "AQUILA_B18";
+
+ status = "okay";
+};
+
+&gpio2 {
+ gpio-line-names = "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AQUILA_B42",
+ "",
+ "AQUILA_B43";
+};
+
+&gpio3 {
+ gpio-line-names = "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AQUILA_A11",
+ "", /* 20 */
+ "AQUILA_B57",
+ "AQUILA_B19";
+};
+
+&gpio4 {
+ gpio-line-names = "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "AQUILA_C22",
+ "AQUILA_C21",
+ "AQUILA_C20",
+ "", /* 20 */
+ "",
+ "",
+ "AQUILA_C23",
+ "AQUILA_D23",
+ "AQUILA_D24",
+ "",
+ "AQUILA_D25";
+};
+
+&gpio5 {
+ gpio-line-names = "", /* 0 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "", /* 10 */
+ "",
+ "",
+ "AQUILA_B44",
+ "AQUILA_B45";
+};
+
+/* Aquila I2C_2 */
+&i3c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i3c2>;
+ i2c-scl-hz = <100000>;
+};
+
+/* Aquila I2C_1 */
+&lpi2c2 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c2>;
+ pinctrl-1 = <&pinctrl_lpi2c2_gpio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+/* On-module I2C - I2C_SOM */
+&lpi2c3 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c3>, <&pinctrl_ctrl_gpio_exp_int>;
+ pinctrl-1 = <&pinctrl_lpi2c3_gpio>, <&pinctrl_ctrl_gpio_exp_int>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <400000>;
+ scl-gpios = <&gpio2 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
+ status = "okay";
+
+ som_gpio_expander_0: gpio@20 {
+ compatible = "nxp,pcal6408";
+ reg = <0x20>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-line-names =
+ "AQUILA_C38", /* 0 */
+ "PCIE_2_RESET#",
+ "AQUILA_B77",
+ "USB_2_H_EN",
+ "BT_DISABLE#",
+ "WIFI_DISABLE#",
+ "CTRL_ETH_REF_CLK_STBY",
+ "CTRL_DP_BRIDGE_EN";
+ };
+
+ som_gpio_expander_1: gpio@21 {
+ compatible = "nxp,pcal6416";
+ reg = <0x21>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupt-parent = <&gpio1>;
+ interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-line-names =
+ "AQUILA_C1", /* 0 */
+ "AQUILA_C2",
+ "AQUILA_C3",
+ "AQUILA_C4",
+ "AQUILA_C36",
+ "AQUILA_B74",
+ "AQUILA_B75",
+ "USB_2_H_OC#",
+ "AQUILA_B81",
+ "PMIC_SD_1_VSEL",
+ "ETH_1_INT#", /* 10 */
+ "CTRL_TPM_INT#",
+ "SPI_2_CS2_TPM",
+ "PCIE_WAKE_WIFI#",
+ "WIFI_WAKE_BT",
+ "WIFI_WAKEUP_HOST";
+ };
+
+ som_dsi2dp_bridge: bridge@2c {
+ compatible = "ti,sn65dsi86";
+ reg = <0x2c>;
+ clocks = <&clk_dsi2dp_refclk_en>;
+ clock-names = "refclk";
+ vcc-supply = <®_dp_1p2v>;
+ vcca-supply = <®_dp_1p2v>;
+ vccio-supply = <®_1p8v>;
+ vpll-supply = <®_1p8v>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ dsi2dp_in: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ dsi2dp_out: endpoint {
+ data-lanes = <3 2 1 0>;
+ };
+ };
+ };
+ };
+
+ rtc_i2c: rtc@32 {
+ compatible = "epson,rx8130";
+ reg = <0x32>;
+ };
+
+ temperature-sensor@48 {
+ compatible = "ti,tmp1075";
+ reg = <0x48>;
+ };
+
+ som_eeprom: eeprom@50 {
+ compatible = "st,24c02", "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+};
+
+/* Aquila I2C_4_CSI1 */
+&lpi2c4 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c4>;
+ pinctrl-1 = <&pinctrl_lpi2c4_gpio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ scl-gpios = <&gpio2 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+/* Aquila I2C_6 */
+&lpi2c5 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c5>;
+ pinctrl-1 = <&pinctrl_lpi2c5_gpio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ scl-gpios = <&gpio2 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+/* Aquila I2C_3_DSI1/I2C_5_CSI2 */
+&lpi2c8 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_lpi2c8>;
+ pinctrl-1 = <&pinctrl_lpi2c8_gpio>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <100000>;
+ scl-gpios = <&gpio2 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio2 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+/* Aquila SPI_2 */
+&lpspi4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi4>;
+ cs-gpios = <&gpio2 18 GPIO_ACTIVE_LOW>,
+ <&som_gpio_expander_1 12 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+
+ som_tpm: tpm@1 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <0x1>;
+ interrupt-parent = <&som_gpio_expander_1>;
+ interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+ /*
+ * Maximum TPM-supported speed is 18.5 MHz, limited to 12 MHz
+ * here as lpspi4's per-clock (2x the max speed) is 24 MHz.
+ */
+ spi-max-frequency = <12000000>;
+ };
+};
+
+/* Aquila SPI_1 */
+&lpspi6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi6>;
+ cs-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+};
+
+/* Aquila UART_3, used as the Linux Console */
+&lpuart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+};
+
+/* Aquila UART_4 */
+&lpuart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+};
+
+/* Aquila UART_1 */
+&lpuart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ uart-has-rtscts;
+};
+
+/* Aquila UART_2 */
+&lpuart7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart7>;
+ uart-has-rtscts;
+};
+
+&mu7 {
+ status = "okay";
+};
+
+/* Aquila ETH_2_XGMII_MDIO, shared between all ethernet ports */
+&netc_emdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emdio>;
+
+ status = "okay";
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ interrupt-parent = <&som_gpio_expander_1>;
+ interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ };
+};
+
+&netcmix_blk_ctrl {
+ status = "okay";
+};
+
+&netc_blk_ctrl {
+ status = "okay";
+};
+
+&netc_timer {
+ status = "okay";
+};
+
+/* Aquila PCIE_1 */
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie0>;
+ reset-gpios = <&som_gpio_expander_0 0 GPIO_ACTIVE_LOW>;
+};
+
+/* On-module Wi-Fi or Aquila PCIE_2 */
+&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie1>;
+ reset-gpios = <&som_gpio_expander_0 1 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+};
+
+/* Aquila I2S_1 */
+&sai2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai2>;
+ assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>,
+ <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>,
+ <&scmi_clk IMX95_CLK_AUDIOPLL1>,
+ <&scmi_clk IMX95_CLK_AUDIOPLL2>,
+ <&scmi_clk IMX95_CLK_SAI2>;
+ assigned-clock-parents = <0>, <0>, <0>, <0>,
+ <&scmi_clk IMX95_CLK_AUDIOPLL1>;
+ assigned-clock-rates = <3932160000>,
+ <3612672000>, <393216000>,
+ <361267200>, <12288000>;
+ #sound-dai-cells = <0>;
+ fsl,sai-mclk-direction-output;
+};
+
+&scmi_bbm {
+ linux,code = <KEY_POWER>;
+};
+
+&thermal_zones {
+ /* PF09 Main PMIC */
+ pf09-thermal {
+ polling-delay = <2000>;
+ polling-delay-passive = <250>;
+ thermal-sensors = <&scmi_sensor 2>;
+
+ trips {
+ trip0 {
+ hysteresis = <2000>;
+ temperature = <155000>;
+ type = "critical";
+ };
+ };
+ };
+
+ /* PF53 VDD_ARM PMIC */
+ pf53-arm-thermal {
+ polling-delay = <2000>;
+ polling-delay-passive = <250>;
+ thermal-sensors = <&scmi_sensor 4>;
+
+ trips {
+ trip0 {
+ hysteresis = <2000>;
+ temperature = <155000>;
+ type = "critical";
+ };
+ };
+ };
+
+ /* PF53 VDD_SOC PMIC */
+ pf53-soc-thermal {
+ polling-delay = <2000>;
+ polling-delay-passive = <250>;
+ thermal-sensors = <&scmi_sensor 3>;
+
+ trips {
+ trip0 {
+ hysteresis = <2000>;
+ temperature = <155000>;
+ type = "critical";
+ };
+ };
+ };
+};
+
+/* Aquila PWM_1 */
+&tpm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+};
+
+/* Aquila PWM_2 */
+&tpm6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+};
+
+/* Aquila PWM_3_DSI and PWM_4_DP */
+&tpm5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3_dsi>, <&pinctrl_pwm4_dp>;
+};
+
+/* Aquila USB_2, optional Bluetooth USB */
+&usb2 {
+ dr_mode = "host";
+ vbus-supply = <®_usb2_vbus>;
+};
+
+/* Aquila USB_1 */
+&usb3 {
+ fsl,disable-port-power-control;
+};
+
+&usb3_dwc3 {
+ dr_mode = "otg";
+ adp-disable;
+ hnp-disable;
+ srp-disable;
+ usb-role-switch;
+};
+
+&usb3_phy {
+ vbus-supply = <®_usb1_vbus>;
+};
+
+/* On-module eMMC */
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ no-sdio;
+ no-sd;
+
+ status = "okay";
+};
+
+/* Aquila SD_1 */
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_sd1_cd_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2>, <&pinctrl_sd1_cd_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>,<&pinctrl_sd1_cd_gpio>;
+ pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_sd1_cd_gpio>;
+ cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <®_usdhc2_vmmc>;
+ vqmmc-supply = <®_usdhc2_vqmmc>;
+};
+
+&wdog3 {
+ fsl,ext-reset-output;
+
+ status = "okay";
+};
+
+&scmi_iomuxc {
+ /* Aquila CTRL_WAKE1_MICO# */
+ pinctrl_ctrl_wake1_mico: ctrlwake1micogrp {
+ fsl,pins = <IMX95_PAD_XSPI1_SS1_B__GPIO5_IO_BIT11 0x31e>; /* Aquila D6 */
+ };
+
+ pinctrl_ctrl_dp_clk_en: dpclkengrp {
+ fsl,pins = <IMX95_PAD_SAI1_TXFS__AONMIX_TOP_GPIO1_IO_BIT11 0x11e>; /* CTRL_DP_CLK_EN */
+ };
+
+ /* Aquila ETH_2_XGMII_MDIO */
+ pinctrl_emdio: emdiogrp {
+ fsl,pins = <IMX95_PAD_ENET2_MDC__NETCMIX_TOP_NETC_MDC 0x57e>, /* Aquila B90 */
+ <IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_NETC_MDIO 0x97e>; /* Aquila B89 */
+ };
+
+ /* Aquila ETH_1 */
+ pinctrl_enetc0: enetc0grp {
+ fsl,pins = <IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RGMII_TX_CTL 0x57e>, /* ENET1_TX_CTL */
+ <IMX95_PAD_ENET1_TXC__NETCMIX_TOP_ETH0_RGMII_TX_CLK 0x58e>, /* ENET1_TXC */
+ <IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0 0x50e>, /* ENET1_TDO */
+ <IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1 0x50e>, /* ENET1_TD1 */
+ <IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2 0x50e>, /* ENET1_TD2 */
+ <IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3 0x50e>, /* ENET1_TD3 */
+ <IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RGMII_RX_CTL 0x57e>, /* ENET1_RX_CTL */
+ <IMX95_PAD_ENET1_RXC__NETCMIX_TOP_ETH0_RGMII_RX_CLK 0x58e>, /* ENET1_RXC */
+ <IMX95_PAD_ENET1_RD0__NETCMIX_TOP_ETH0_RGMII_RD0 0x57e>, /* ENET1_RD0 */
+ <IMX95_PAD_ENET1_RD1__NETCMIX_TOP_ETH0_RGMII_RD1 0x57e>, /* ENET1_RD1 */
+ <IMX95_PAD_ENET1_RD2__NETCMIX_TOP_ETH0_RGMII_RD2 0x57e>, /* ENET1_RD2 */
+ <IMX95_PAD_ENET1_RD3__NETCMIX_TOP_ETH0_RGMII_RD3 0x57e>; /* ENET1_RD3 */
+ };
+
+ /* Aquila CAN_1 */
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <IMX95_PAD_PDM_CLK__AONMIX_TOP_CAN1_TX 0x39e>, /* Aquila B48 */
+ <IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_CAN1_RX 0x39e>; /* Aquila B49 */
+ };
+
+ /* Aquila CAN_2 */
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO25__CAN2_TX 0x39e>, /* Aquila B50 */
+ <IMX95_PAD_GPIO_IO27__CAN2_RX 0x39e>; /* Aquila B51 */
+ };
+
+ /* Aquila CAN_3 */
+ pinctrl_flexcan3: flexcan3grp {
+ fsl,pins = <IMX95_PAD_CCM_CLKO3__CAN3_TX 0x39e>, /* Aquila B53 */
+ <IMX95_PAD_CCM_CLKO4__CAN3_RX 0x39e>; /* Aquila B54 */
+ };
+
+ /* Aquila CAN_4 */
+ pinctrl_flexcan4: flexcan4grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO04__CAN4_TX 0x39e>, /* Aquila B55 */
+ <IMX95_PAD_GPIO_IO05__CAN4_RX 0x39e>; /* Aquila B56 */
+ };
+
+ /* Aquila QSPI_1 (4 bit) */
+ pinctrl_flexspi1_4bit: flexspi14bitgrp {
+ fsl,pins = <IMX95_PAD_XSPI1_SCLK__FLEXSPI1_A_SCLK 0x3fe>, /* Aquila B65 */
+ <IMX95_PAD_XSPI1_DATA0__FLEXSPI1_A_DATA_BIT0 0x3fe>, /* Aquila B68 */
+ <IMX95_PAD_XSPI1_DATA1__FLEXSPI1_A_DATA_BIT1 0x3fe>, /* Aquila B67 */
+ <IMX95_PAD_XSPI1_DATA2__FLEXSPI1_A_DATA_BIT2 0x3fe>, /* Aquila B61 */
+ <IMX95_PAD_XSPI1_DATA3__FLEXSPI1_A_DATA_BIT3 0x3fe>, /* Aquila B60 */
+ <IMX95_PAD_XSPI1_DQS__FLEXSPI1_A_DQS 0x3fe>; /* Aquila B63 */
+ };
+
+ /* Aquila QSPI_1 (8 bit) */
+ pinctrl_flexspi1_8bit: flexspi18bitgrp {
+ fsl,pins = <IMX95_PAD_XSPI1_SCLK__FLEXSPI1_A_SCLK 0x3fe>, /* Aquila B65 */
+ <IMX95_PAD_XSPI1_DATA0__FLEXSPI1_A_DATA_BIT0 0x3fe>, /* Aquila B68 */
+ <IMX95_PAD_XSPI1_DATA1__FLEXSPI1_A_DATA_BIT1 0x3fe>, /* Aquila B67 */
+ <IMX95_PAD_XSPI1_DATA2__FLEXSPI1_A_DATA_BIT2 0x3fe>, /* Aquila B61 */
+ <IMX95_PAD_XSPI1_DATA3__FLEXSPI1_A_DATA_BIT3 0x3fe>, /* Aquila B60 */
+ <IMX95_PAD_XSPI1_DATA4__FLEXSPI1_A_DATA_BIT4 0x3fe>, /* Aquila B70 */
+ <IMX95_PAD_XSPI1_DATA5__FLEXSPI1_A_DATA_BIT5 0x3fe>, /* Aquila B71 */
+ <IMX95_PAD_XSPI1_DATA6__FLEXSPI1_A_DATA_BIT6 0x3fe>, /* Aquila B72 */
+ <IMX95_PAD_XSPI1_DATA7__FLEXSPI1_A_DATA_BIT7 0x3fe>, /* Aquila B73 */
+ <IMX95_PAD_XSPI1_DQS__FLEXSPI1_A_DQS 0x3fe>; /* Aquila B63 */
+ };
+
+ /* Aquila GPIO_01 */
+ pinctrl_gpio_1: gpio1grp {
+ fsl,pins = <IMX95_PAD_ENET2_RD0__GPIO4_IO_BIT24 0x31e>; /* Aquila D23 */
+ };
+
+ /* Aquila GPIO_02 */
+ pinctrl_gpio_2: gpio2grp {
+ fsl,pins = <IMX95_PAD_ENET2_RD1__GPIO4_IO_BIT25 0x31e>; /* Aquila D24 */
+ };
+
+ /* Aquila GPIO_03 */
+ pinctrl_gpio_3: gpio3grp {
+ fsl,pins = <IMX95_PAD_ENET2_RD3__GPIO4_IO_BIT27 0x31e>; /* Aquila D25 */
+ };
+
+ /* Aquila GPIO_04 */
+ pinctrl_gpio_4: gpio4grp {
+ fsl,pins = <IMX95_PAD_ENET2_TD0__GPIO4_IO_BIT19 0x31e>; /* Aquila C20 */
+ };
+
+ /* Aquila GPIO_05 */
+ pinctrl_gpio_5: gpio5grp {
+ fsl,pins = <IMX95_PAD_ENET2_TD1__GPIO4_IO_BIT18 0x31e>; /* Aquila C21 */
+ };
+
+ /* Aquila GPIO_06 */
+ pinctrl_gpio_6: gpio6grp {
+ fsl,pins = <IMX95_PAD_ENET2_TD2__GPIO4_IO_BIT17 0x31e>; /* Aquila C22 */
+ };
+
+ /* Aquila GPIO_07 */
+ pinctrl_gpio_7: gpio7grp {
+ fsl,pins = <IMX95_PAD_ENET2_RXC__GPIO4_IO_BIT23 0x31e>; /* Aquila C23 */
+ };
+
+ /* Aquila GPIO_08 */
+ pinctrl_gpio_8: gpio8grp {
+ fsl,pins = <IMX95_PAD_PDM_BIT_STREAM1__AONMIX_TOP_GPIO1_IO_BIT10 0x31e>; /* Aquila C24 */
+ };
+
+ /* Aquila GPIO_09_CSI_1 */
+ pinctrl_gpio_9_csi_1: gpio9csi1grp {
+ fsl,pins = <IMX95_PAD_SAI1_TXC__AONMIX_TOP_GPIO1_IO_BIT12 0x31e>; /* Aquila B17 */
+ };
+
+ /* Aquila GPIO_10_CSI_1 */
+ pinctrl_gpio_10_csi_1: gpio10csi1grp {
+ fsl,pins = <IMX95_PAD_SAI1_RXD0__AONMIX_TOP_GPIO1_IO_BIT14 0x31e>; /* Aquila B18 */
+ };
+
+ /* Aquila GPIO_11_CSI_1 */
+ pinctrl_gpio_11_csi_1: gpio11csi1grp {
+ fsl,pins = <IMX95_PAD_SD2_VSELECT__GPIO3_IO_BIT19 0x31e>; /* Aquila A11*/
+ };
+
+ /* Aquila GPIO_12_CSI_1 */
+ pinctrl_gpio_12_csi_1: gpio12csi1grp {
+ fsl,pins = <IMX95_PAD_SD3_DATA0__GPIO3_IO_BIT22 0x31e>; /* Aquila B19 */
+ };
+
+ /* Aquila GPIO_17_DSI_1 */
+ pinctrl_gpio_17_dsi_1: gpio17dsi1grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO07__GPIO2_IO_BIT7 0x31e>; /* Aquila B42 */
+ };
+
+ /* Aquila GPIO_18_DSI_1 */
+ pinctrl_gpio_18_dsi_1: gpio18dsi1grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO09__GPIO2_IO_BIT9 0x31e>; /* Aquila B43 */
+ };
+
+ /* Aquila GPIO_19_DSI_1 */
+ pinctrl_gpio_19_dsi_1: gpio19dsi1grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO33__GPIO5_IO_BIT13 0x31e>; /* Aquila B44 */
+ };
+
+ /* Aquila GPIO_20_DSI_1 */
+ pinctrl_gpio_20_dsi_1: gpio20dsi1grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO34__GPIO5_IO_BIT14 0x31e>; /* Aquila B45 */
+ };
+
+ /* Aquila GPIO_21_DP */
+ pinctrl_gpio_21_dp: gpio21dpgrp {
+ fsl,pins = <IMX95_PAD_SD3_CMD__GPIO3_IO_BIT21 0x31e>; /* Aquila B57 */
+ };
+
+ pinctrl_ctrl_gpio_exp_int: gpioexpintgrp {
+ fsl,pins = <IMX95_PAD_SAI1_TXD0__AONMIX_TOP_GPIO1_IO_BIT13 0x31e>; /* CTRL_GPIO_EXP_INT# */
+ };
+
+ /* Aquila I2C_2 */
+ pinctrl_i3c2: i3c2cgrp {
+ fsl,pins = <IMX95_PAD_ENET1_MDC__I3C2_SCL 0x40001186>, /* Aquila C17 */
+ <IMX95_PAD_ENET1_MDIO__I3C2_SDA 0x40001186>; /* Aquila C16 */
+ };
+
+ /* Aquila I2C_1 as GPIOs */
+ pinctrl_lpi2c2_gpio: lpi2c2gpiogrp {
+ fsl,pins = <IMX95_PAD_I2C2_SCL__AONMIX_TOP_GPIO1_IO_BIT2 0x40001b9e>, /* Aquila D8 */
+ <IMX95_PAD_I2C2_SDA__AONMIX_TOP_GPIO1_IO_BIT3 0x40001b9e>; /* Aquila D7 */
+ };
+
+ /* Aquila I2C_1 */
+ pinctrl_lpi2c2: lpi2c2grp {
+ fsl,pins = <IMX95_PAD_I2C2_SCL__AONMIX_TOP_LPI2C2_SCL 0x40001b9e>, /* Aquila D8 */
+ <IMX95_PAD_I2C2_SDA__AONMIX_TOP_LPI2C2_SDA 0x40001b9e>; /* Aquila D7 */
+ };
+
+ /* On-module I2C as GPIOs */
+ pinctrl_lpi2c3_gpio: lpi2c3gpiogrp {
+ fsl,pins = <IMX95_PAD_GPIO_IO28__GPIO2_IO_BIT28 0x40001b9e>, /* I2C_SOM_SDA */
+ <IMX95_PAD_GPIO_IO29__GPIO2_IO_BIT29 0x40001b9e>; /* I2C_SOM_SCL */
+ };
+
+ /* On-module I2C */
+ pinctrl_lpi2c3: lpi2c3grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO28__LPI2C3_SDA 0x40001b9e>, /* I2C_SOM_SDA */
+ <IMX95_PAD_GPIO_IO29__LPI2C3_SCL 0x40001b9e>; /* I2C_SOM_SCL */
+ };
+
+ /* Aquila I2C_4_CSI1 as GPIO */
+ pinctrl_lpi2c4_gpio: lpi2c4gpiogrp {
+ fsl,pins = <IMX95_PAD_GPIO_IO30__GPIO2_IO_BIT30 0x40001b9e>, /* Aquila A12 */
+ <IMX95_PAD_GPIO_IO31__GPIO2_IO_BIT31 0x40001b9e>; /* Aquila A13 */
+ };
+
+ /* Aquila I2C_4_CSI1 */
+ pinctrl_lpi2c4: lpi2c4grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO30__LPI2C4_SDA 0x40001b9e>, /* Aquila A12 */
+ <IMX95_PAD_GPIO_IO31__LPI2C4_SCL 0x40001b9e>; /* Aquila A13 */
+ };
+
+ /* Aquila I2C_6 as GPIO */
+ pinctrl_lpi2c5_gpio: lpi2c5gpiogrp {
+ fsl,pins = <IMX95_PAD_GPIO_IO22__GPIO2_IO_BIT22 0x40001b9e>, /* Aquila C18 */
+ <IMX95_PAD_GPIO_IO23__GPIO2_IO_BIT23 0x40001b9e>; /* Aquila C19 */
+ };
+
+ /* Aquila I2C_6 */
+ pinctrl_lpi2c5: lpi2c5grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO22__LPI2C5_SDA 0x40001b9e>, /* Aquila C18 */
+ <IMX95_PAD_GPIO_IO23__LPI2C5_SCL 0x40001b9e>; /* Aquila C19 */
+ };
+
+ /* Aquila I2C_3_DSI1/I2C_5_CSI2 as GPIO */
+ pinctrl_lpi2c8_gpio: lpi2c8gpiogrp {
+ fsl,pins = <IMX95_PAD_GPIO_IO12__GPIO2_IO_BIT12 0x40001b9e>, /* Aquila C5/B40 */
+ <IMX95_PAD_GPIO_IO13__GPIO2_IO_BIT13 0x40001b9e>; /* Aquila C6/B41 */
+ };
+
+ /* Aquila I2C_3_DSI1/I2C_5_CSI2 */
+ pinctrl_lpi2c8: lpi2c8grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO12__LPI2C8_SDA 0x40001b9e>, /* Aquila C5/B40 */
+ <IMX95_PAD_GPIO_IO13__LPI2C8_SCL 0x40001b9e>; /* Aquila C6/B41 */
+ };
+
+ /* Aquila SPI_2 */
+ pinctrl_lpspi4: lpspi4grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO18__GPIO2_IO_BIT18 0x3fe>, /* Aquila D16 */
+ <IMX95_PAD_GPIO_IO19__LPSPI4_SIN 0x3fe>, /* Aquila D15 */
+ <IMX95_PAD_GPIO_IO20__LPSPI4_SOUT 0x3fe>, /* Aquila D17 */
+ <IMX95_PAD_GPIO_IO21__LPSPI4_SCK 0x3fe>; /* Aquila D14 */
+ };
+
+ /* Aquila SPI_1 */
+ pinctrl_lpspi6: lpspi6grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO00__GPIO2_IO_BIT0 0x3fe>, /* Aquila D9 */
+ <IMX95_PAD_GPIO_IO01__LPSPI6_SIN 0x3fe>, /* Aquila D10 */
+ <IMX95_PAD_GPIO_IO02__LPSPI6_SOUT 0x3fe>, /* Aquila D11 */
+ <IMX95_PAD_GPIO_IO03__LPSPI6_SCK 0x3fe>; /* Aquila D12 */
+ };
+
+ /* Aquila PCIE_1 */
+ pinctrl_pcie0: pcie0grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO32__HSIOMIX_TOP_PCIE1_CLKREQ_B 0x40001b1e>; /* Aquila C37 */
+ };
+
+ /* Aquila PCIE_2 */
+ pinctrl_pcie1: pcie1grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO35__HSIOMIX_TOP_PCIE2_CLKREQ_B 0x40001b1e>; /* Aquila C34 */
+ };
+
+ /* Aquila QSPI_1_CS1# */
+ pinctrl_qspi_cs1: qspics1grp {
+ fsl,pins = <IMX95_PAD_XSPI1_SS0_B__FLEXSPI1_A_SS0_B 0x3fe>; /* Aquila B66 */
+ };
+
+ /* Aquila QSPI_1_CS2# as GPIO */
+ pinctrl_qspi_cs2_gpio: qspics2gpiogrp {
+ fsl,pins = <IMX95_PAD_CCM_CLKO2__GPIO3_IO_BIT27 0x3fe>; /* Aquila B62 */
+ };
+
+ /* Aquila I2S_1 */
+ pinctrl_sai2: sai2grp {
+ fsl,pins = <IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_SAI2_TX_SYNC 0x11e>, /* Aquila B21 */
+ <IMX95_PAD_ENET2_TXC__NETCMIX_TOP_SAI2_TX_BCLK 0x11e>, /* Aquila B20 */
+ <IMX95_PAD_ENET2_TD3__NETCMIX_TOP_SAI2_RX_DATA_BIT0 0x11e>, /* Aquila B23 */
+ <IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_SAI2_TX_DATA_BIT0 0x11e>; /* Aquila B22 */
+ };
+
+ pinctrl_sai2_mclk: sai2mclkgrp {
+ fsl,pins = <IMX95_PAD_ENET2_RD2__NETCMIX_TOP_SAI2_MCLK 0x31e>; /* Aquila B24 */
+ };
+
+ /* Aquila SD_1_CD# as GPIO */
+ pinctrl_sd1_cd_gpio: sd1cdgpiogrp {
+ fsl,pins = <IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0 0x1100>; /* Aquila A1 */
+ };
+
+ /* Aquila SD_1_PWR_EN */
+ pinctrl_sd1_pwr_en: sd1pwrengpiogrp {
+ fsl,pins = <IMX95_PAD_SD2_RESET_B__GPIO3_IO_BIT7 0x11e>; /* Aquila A6 */
+ };
+
+ /* Aquila PWM_1 */
+ pinctrl_pwm1: tpm3ch3grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO24__TPM3_CH3 0x11e>; /* Aquila C25 */
+ };
+
+ /* Aquila PWM_3_DSI as GPIO */
+ pinctrl_pwm3_dsi_gpio: tpm5ch0gpiogrp {
+ fsl,pins = <IMX95_PAD_GPIO_IO06__GPIO2_IO_BIT6 0x11e>; /* Aquila B46 */
+ };
+
+ /* Aquila PWM_3_DSI */
+ pinctrl_pwm3_dsi: tpm5ch0grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO06__TPM5_CH0 0x11e>; /* Aquila B46 */
+ };
+
+ /* Aquila PWM_4_DP */
+ pinctrl_pwm4_dp: tpm5ch3grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO26__TPM5_CH3 0x11e>; /* Aquila B58 */
+ };
+
+ /* Aquila PWM_2 */
+ pinctrl_pwm2: tpm6ch0grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO08__TPM6_CH0 0x11e>; /* Aquila C26 */
+ };
+
+ /* Aquila UART_3 */
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <IMX95_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX 0x31e>, /* Aquila D20 */
+ <IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX 0x31e>; /* Aquila D19 */
+ };
+
+ /* Aquila UART_4 */
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <IMX95_PAD_UART2_TXD__AONMIX_TOP_LPUART2_TX 0x31e>, /* Aquila D22 */
+ <IMX95_PAD_UART2_RXD__AONMIX_TOP_LPUART2_RX 0x31e>; /* Aquila D21 */
+ };
+
+ /* Aquila UART_1 */
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO14__LPUART3_TX 0x31e>, /* Aquila B37 */
+ <IMX95_PAD_GPIO_IO15__LPUART3_RX 0x31e>, /* Aquila B35 */
+ <IMX95_PAD_GPIO_IO16__LPUART3_CTS_B 0x31e>, /* Aquila B36 */
+ <IMX95_PAD_GPIO_IO17__LPUART3_RTS_B 0x31e>; /* Aquila B38 */
+ };
+
+ /* Aquila UART_2 */
+ pinctrl_uart7: uart7grp {
+ fsl,pins = <IMX95_PAD_GPIO_IO36__LPUART7_TX 0x31e>, /* Aquila B33 */
+ <IMX95_PAD_GPIO_IO37__LPUART7_RX 0x31e>, /* Aquila B31 */
+ <IMX95_PAD_GPIO_IO10__LPUART7_CTS_B 0x31e>, /* Aquila B32 */
+ <IMX95_PAD_GPIO_IO11__LPUART7_RTS_B 0x31e>; /* Aquila B34 */
+ };
+
+ /* On-module eMMC */
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <IMX95_PAD_SD1_CLK__USDHC1_CLK 0x158e>, /* eMMC_CLK */
+ <IMX95_PAD_SD1_CMD__USDHC1_CMD 0x138e>, /* eMMC_CMD */
+ <IMX95_PAD_SD1_DATA0__USDHC1_DATA0 0x138e>, /* eMMC_DATA0 */
+ <IMX95_PAD_SD1_DATA1__USDHC1_DATA1 0x138e>, /* eMMC_DATA1 */
+ <IMX95_PAD_SD1_DATA2__USDHC1_DATA2 0x138e>, /* eMMC_DATA2 */
+ <IMX95_PAD_SD1_DATA3__USDHC1_DATA3 0x138e>, /* eMMC_DATA3 */
+ <IMX95_PAD_SD1_DATA4__USDHC1_DATA4 0x138e>, /* eMMC_DATA4 */
+ <IMX95_PAD_SD1_DATA5__USDHC1_DATA5 0x138e>, /* eMMC_DATA5 */
+ <IMX95_PAD_SD1_DATA6__USDHC1_DATA6 0x138e>, /* eMMC_DATA6 */
+ <IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x138e>, /* eMMC_DATA7 */
+ <IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x158e>; /* eMMC_STROBE */
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
+ fsl,pins = <IMX95_PAD_SD1_CLK__USDHC1_CLK 0x15fe>, /* eMMC_CLK */
+ <IMX95_PAD_SD1_CMD__USDHC1_CMD 0x13fe>, /* eMMC_CMD */
+ <IMX95_PAD_SD1_DATA0__USDHC1_DATA0 0x13fe>, /* eMMC_DATA0 */
+ <IMX95_PAD_SD1_DATA1__USDHC1_DATA1 0x13fe>, /* eMMC_DATA1 */
+ <IMX95_PAD_SD1_DATA2__USDHC1_DATA2 0x13fe>, /* eMMC_DATA2 */
+ <IMX95_PAD_SD1_DATA3__USDHC1_DATA3 0x13fe>, /* eMMC_DATA3 */
+ <IMX95_PAD_SD1_DATA4__USDHC1_DATA4 0x13fe>, /* eMMC_DATA4 */
+ <IMX95_PAD_SD1_DATA5__USDHC1_DATA5 0x13fe>, /* eMMC_DATA5 */
+ <IMX95_PAD_SD1_DATA6__USDHC1_DATA6 0x13fe>, /* eMMC_DATA6 */
+ <IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x13fe>, /* eMMC_DATA7 */
+ <IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe>; /* eMMC_STROBE */
+ };
+
+ /* Aquila SD_1 */
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <IMX95_PAD_SD2_CLK__USDHC2_CLK 0x158e>, /* Aquila A5 */
+ <IMX95_PAD_SD2_CMD__USDHC2_CMD 0x138e>, /* Aquila A7 */
+ <IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x138e>, /* Aquila A3 */
+ <IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x138e>, /* Aquila A2 */
+ <IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x138e>, /* Aquila A10 */
+ <IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x138e>; /* Aquila A8 */
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <IMX95_PAD_SD2_CLK__USDHC2_CLK 0x15fe>, /* Aquila A5 */
+ <IMX95_PAD_SD2_CMD__USDHC2_CMD 0x13fe>, /* Aquila A7 */
+ <IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x13fe>, /* Aquila A3 */
+ <IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x13fe>, /* Aquila A2 */
+ <IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x13fe>, /* Aquila A10 */
+ <IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x13fe>; /* Aquila A8 */
+ };
+
+ pinctrl_usdhc2_sleep: usdhc2-sleepgrp {
+ fsl,pins = <IMX95_PAD_SD2_CLK__USDHC2_CLK 0x400>, /* Aquila A5 */
+ <IMX95_PAD_SD2_CMD__USDHC2_CMD 0x400>, /* Aquila A7 */
+ <IMX95_PAD_SD2_DATA0__USDHC2_DATA0 0x400>, /* Aquila A3 */
+ <IMX95_PAD_SD2_DATA1__USDHC2_DATA1 0x400>, /* Aquila A2 */
+ <IMX95_PAD_SD2_DATA2__USDHC2_DATA2 0x400>, /* Aquila A10 */
+ <IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x400>; /* Aquila A8 */
+ };
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v4 3/3] arm64: dts: freescale: imx95-aquila: Add Clover carrier board
From: Franz Schnyder @ 2026-05-21 17:11 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, linux-kernel, imx, linux-arm-kernel,
Francesco Dolcini, Franz Schnyder, Antoine Gouby
In-Reply-To: <20260521-add-aquila-imx95-v4-0-5a7f86c824f5@toradex.com>
From: Antoine Gouby <antoine.gouby@toradex.com>
Add support for the Aquila i.MX95 SoM mated with the Clover carrier
board. Clover is a low-cost carrier board for the Aquila family
featuring a small form factor (Nano-ITX 120mm x 120mm) and built for
volume production.
Link: https://www.toradex.com/computer-on-modules/aquila-arm-family/nxp-imx95
Link: https://www.toradex.com/products/carrier-board/clover
Signed-off-by: Antoine Gouby <antoine.gouby@toradex.com>
Signed-off-by: Franz Schnyder <franz.schnyder@toradex.com>
---
v4: Removed som_dsi2dp_bridge node since SoC's DSI controller is unsupported
v3: Deleted the cdns,* properties from flexspi1
v2: no changes
v1: https://lore.kernel.org/all/20260506-add-aquila-imx95-v1-3-69c8ee1c5413@toradex.com/
---
arch/arm64/boot/dts/freescale/Makefile | 1 +
.../boot/dts/freescale/imx95-aquila-clover.dts | 285 +++++++++++++++++++++
2 files changed, 286 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index c8697b6ae01c5..3ce082c121036 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -523,6 +523,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-frdm.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-sof.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-clover.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-dev.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-toradex-smarc-dev.dtb
dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596sa-mb-smarc-2.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts b/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts
new file mode 100644
index 0000000000000..fd93043314466
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (c) Toradex
+ *
+ * https://www.toradex.com/computer-on-modules/aquila-arm-family/nxp-imx95
+ * https://www.toradex.com/products/carrier-board/clover
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/usb/pd.h>
+#include "imx95-aquila.dtsi"
+
+/ {
+ model = "Aquila iMX95 on Aquila Clover Board";
+ compatible = "toradex,aquila-imx95-clover",
+ "toradex,aquila-imx95",
+ "fsl,imx95";
+
+ aliases {
+ eeprom1 = &carrier_eeprom;
+ };
+
+ dp_1_connector: dp0-connector {
+ compatible = "dp-connector";
+ dp-pwr-supply = <®_dp_3p3v>;
+ type = "full-size";
+
+ port {
+ dp_1_connector_in: endpoint {
+ remote-endpoint = <&dsi2dp_out>;
+ };
+ };
+ };
+
+ reg_dp_3p3v: regulator-dp-3p3v {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_21_dp>;
+ /* Aquila GPIO_21_DP */
+ gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "DP_3V3";
+ startup-delay-us = <10000>;
+ };
+};
+
+/* Aquila ADC_[1-4] */
+&adc1 {
+ status = "okay";
+};
+
+/* Aquila CTRL_WAKE1_MICO# */
+&aquila_key_wake {
+ status = "okay";
+};
+
+&dsi2dp_out {
+ remote-endpoint = <&dp_1_connector_in>;
+};
+
+/* Aquila ETH_1 */
+&enetc_port0 {
+ status = "okay";
+};
+
+/* Aquila CAN_1 */
+&flexcan1 {
+ status = "okay";
+};
+
+/* Aquila CAN_2 */
+&flexcan2 {
+ status = "okay";
+};
+
+/* Aquila CAN_3 */
+&flexcan3 {
+ status = "okay";
+};
+
+/* Aquila CAN_4 */
+&flexcan4 {
+ status = "okay";
+};
+
+/* Aquila QSPI_1 */
+&flexspi1 {
+ pinctrl-0 = <&pinctrl_flexspi1_4bit>,
+ <&pinctrl_qspi_cs1>;
+
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <66000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+ };
+};
+
+&gpio4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_1>,
+ <&pinctrl_gpio_2>,
+ <&pinctrl_gpio_3>,
+ <&pinctrl_gpio_4>;
+};
+
+/* Aquila I2C_2 */
+&i3c2 {
+ status = "okay";
+};
+
+/* Aquila I2C_1 */
+&lpi2c2 {
+ status = "okay";
+
+ fan_controller: fan@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ #pwm-cells = <2>;
+
+ fan {
+ cooling-levels = <255>;
+ pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>;
+ };
+ };
+
+ temperature-sensor@4f {
+ compatible = "ti,tmp1075";
+ reg = <0x4f>;
+ };
+
+ /* USB-C OTG (TCPC USB PD PHY) */
+ tcpc@52 {
+ compatible = "nxp,ptn5110", "tcpci";
+ reg = <0x52>;
+ interrupt-parent = <&som_gpio_expander_1>;
+ interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+
+ connector {
+ compatible = "usb-c-connector";
+ data-role = "dual";
+ op-sink-microwatt = <0>;
+ power-role = "dual";
+ self-powered;
+ sink-pdos = <PDO_FIXED(5000, 0, PDO_FIXED_USB_COMM)>;
+ source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ try-power-role = "sink";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ typec_con_hs: endpoint {
+ remote-endpoint = <&usb1_con_hs>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ typec_con_ss: endpoint {
+ remote-endpoint = <&usb1_con_ss>;
+ };
+ };
+ };
+ };
+ };
+
+ carrier_eeprom: eeprom@57 {
+ compatible = "st,24c02", "atmel,24c02";
+ reg = <0x57>;
+ pagesize = <16>;
+ };
+};
+
+/* Aquila I2C_6 */
+&lpi2c5 {
+ status = "okay";
+};
+
+/* Aquila SPI_1 */
+&lpspi6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi6 &pinctrl_gpio_5>;
+ cs-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>, <&gpio4 18 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+
+ tpm@1 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_6>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ spi-max-frequency = <12000000>;
+ };
+};
+
+/* Aquila UART_3, used as the Linux Console */
+&lpuart1 {
+ status = "okay";
+};
+
+/* Aquila UART_4 */
+&lpuart2 {
+ status = "okay";
+};
+
+/* Aquila UART_1 */
+&lpuart3 {
+ status = "okay";
+};
+
+/* Aquila UART_2 */
+&lpuart7 {
+ status = "okay";
+};
+
+/* Aquila PCIE_1 */
+&pcie0 {
+ status = "okay";
+};
+
+/* Aquila PWM_1 */
+&tpm3 {
+ status = "okay";
+};
+
+/* Aquila PWM_3_DSI and PWM_4_DP */
+&tpm5 {
+ status = "okay";
+};
+
+/* Aquila PWM_2 */
+&tpm6 {
+ status = "okay";
+};
+
+/* Aquila USB_2, optional Bluetooth USB */
+&usb2 {
+ status = "okay";
+};
+
+/* Aquila USB_1 */
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ status = "okay";
+
+ port {
+ usb1_con_hs: endpoint {
+ remote-endpoint = <&typec_con_hs>;
+ };
+ };
+};
+
+&usb3_phy {
+ orientation-switch;
+
+ status = "okay";
+
+ port {
+ usb1_con_ss: endpoint {
+ remote-endpoint = <&typec_con_ss>;
+ };
+ };
+};
+
+/* Aquila SD_1 */
+&usdhc2 {
+ status = "okay";
+};
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v4 04/13] dma: swiotlb: track pool encryption state and honor DMA_ATTR_CC_SHARED
From: Aneesh Kumar K.V @ 2026-05-21 17:20 UTC (permalink / raw)
To: Mostafa Saleh
Cc: iommu, linux-arm-kernel, linux-kernel, linux-coco, Robin Murphy,
Marek Szyprowski, Will Deacon, Marc Zyngier, Steven Price,
Suzuki K Poulose, Catalin Marinas, Jiri Pirko, Jason Gunthorpe,
Petr Tesarik, Alexey Kardashevskiy, Dan Williams, Xu Yilun,
linuxppc-dev, linux-s390, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
Christian Borntraeger, Sven Schnelle, x86
In-Reply-To: <CAFgf54o4ZnvnJ3369bHb10tvJJVP+5YWq=ec4Jh5K6S6U9uNEA@mail.gmail.com>
Mostafa Saleh <smostafa@google.com> writes:
> On Tue, May 12, 2026 at 10:05 AM Aneesh Kumar K.V (Arm)
> <aneesh.kumar@kernel.org> wrote:
>> @@ -1411,6 +1436,16 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
>> if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
>> pr_warn_once("Memory encryption is active and system is using DMA bounce buffers\n");
>>
>> + /*
>> + * if we are trying to swiotlb map a decrypted paddr or the paddr is encrypted
>> + * but the device is forcing decryption, use decrypted io_tlb_mem
>> + */
>> + if ((attrs & DMA_ATTR_CC_SHARED) || force_dma_unencrypted(dev))
>
> I don't think swiotlb needs to know about force_dma_unencrypted(), the
> dma/direct caller should have all the information to pass the
> appropriate flags.
>
> Thanks.
> Mostafa
>
>> + require_decrypted = true;
>> +
>> + if (require_decrypted != mem->unencrypted)
>> + return (phys_addr_t)DMA_MAPPING_ERROR;
>> +
Based on other email threads, this is now updated to
@@ -1372,9 +1417,19 @@ static unsigned long mem_used(struct io_tlb_mem *mem)
* any pre- or post-padding for alignment
* @alloc_align_mask: Required start and end alignment of the allocated buffer
* @dir: DMA direction
- * @attrs: Optional DMA attributes for the map operation
+ * @attrs: Optional DMA attributes for the map operation, updated
+ * to match the selected SWIOTLB pool
*
* Find and allocate a suitable sequence of IO TLB slots for the request.
+ * The device's SWIOTLB pool must match the device's current DMA encryption
+ * requirements. If the device requires decrypted DMA, bouncing is done through
+ * an unencrypted pool and the mapping is marked shared. If the device can DMA
+ * to encrypted memory, bouncing is done through an encrypted pool even when the
+ * original DMA address was unencrypted. Enabling encrypted DMA for a device is
+ * therefore expected to update its default io_tlb_mem to an encrypted pool, so
+ * later bounce mappings for both encrypted and decrypted original memory use
+ * that encrypted pool.
+ *
* The allocated space starts at an alignment specified by alloc_align_mask,
* and the size of the allocated space is rounded up so that the total amount
* of allocated space is a multiple of (alloc_align_mask + 1). If
@@ -1411,6 +1466,16 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
pr_warn_once("Memory encryption is active and system is using DMA bounce buffers\n");
+ /* swiotlb pool is incorrect for this device */
+ if (unlikely(mem->unencrypted != force_dma_unencrypted(dev)))
+ return (phys_addr_t)DMA_MAPPING_ERROR;
+
+ /* Force attrs to match the kind of memory in the pool */
+ if (mem->unencrypted)
+ *attrs |= DMA_ATTR_CC_SHARED;
+ else
+ *attrs &= ~DMA_ATTR_CC_SHARED;
+
/*
* The default swiotlb memory pool is allocated with PAGE_SIZE
* alignment. If a mapping is requested with larger alignment,
@@ -1608,8 +1673,11 @@ dma_addr_t swiotlb_map(struct device *dev, phys_addr_t paddr, size_t size,
if (swiotlb_addr == (phys_addr_t)DMA_MAPPING_ERROR)
return DMA_MAPPING_ERROR;
- /* Ensure that the address returned is DMA'ble */
- dma_addr = phys_to_dma_unencrypted(dev, swiotlb_addr);
+ if (attrs & DMA_ATTR_CC_SHARED)
+ dma_addr = phys_to_dma_unencrypted(dev, swiotlb_addr);
+ else
+ dma_addr = phys_to_dma_encrypted(dev, swiotlb_addr);
+
if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
__swiotlb_tbl_unmap_single(dev, swiotlb_addr, size, dir,
attrs | DMA_ATTR_SKIP_CPU_SYNC,
@@ -1773,7 +1841,7 @@ static inline void swiotlb_create_debugfs_files(struct io_tlb_mem *mem,
^ permalink raw reply
* Re: [PATCH 7/8] sched_ext: Sub-allocator over kernel-claimed BPF arena pages
From: Tejun Heo @ 2026-05-21 17:22 UTC (permalink / raw)
To: Andrea Righi
Cc: David Vernet, Changwoo Min, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Peter Zijlstra, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, Andrew Morton,
David Hildenbrand, Mike Rapoport, Emil Tsalapatis, sched-ext, bpf,
x86, linux-arm-kernel, linux-mm, linux-kernel
In-Reply-To: <ag66lfvACAEAI9w8@gpd4>
Hello,
On Thu, May 21, 2026 at 09:56:05AM +0200, Andrea Righi wrote:
> IIUC, since @page_cnt is sized to cover @size and the new chunk is added empty
> to the pool, gen_pool_alloc() here should always succeed. Should we do:
>
> if (WARN_ON_ONCE(!kern_va))
> return NULL;
>
> to catch potential logical bugs / future concurrency / exotic configurations?
Good point. It works for a single caller, but a concurrent one could drain
the new chunk between grow and retry. I'll switch it to a loop.
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH 1/5] arm_mpam: Parse the rest of the ACPI table
From: Srivathsa L Rao @ 2026-05-21 17:27 UTC (permalink / raw)
To: Andre Przywara, Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla,
Catalin Marinas, Will Deacon, Rafael J . Wysocki, Len Brown,
James Morse, Ben Horgan, Reinette Chatre, Fenghua Yu
Cc: Jonathan Cameron, linux-acpi, linux-arm-kernel, linux-kernel,
Ganapatrao Kulkarni
In-Reply-To: <20260429141339.3171205-2-andre.przywara@arm.com>
Hi Andre,
On 4/29/2026 7:43 PM, Andre Przywara wrote:
> From: James Morse<james.morse@arm.com>
>
> The MPAM ACPI table lists the MPAM MSCs and indicates which resources
> in the system they control. Not everything this table can describe is
> supported by resctrl, e.g. memory-side-caches.
>
> Add the additional table parsing to avoid reporting these as 'unknown'
> to the MPAM driver. This allows class+component hierarchys to be built.
>
> Until resctrl has support for any of these resources, users would be
> in-kernel managers of a resource/PARTID or perf to query bandwidth
> counters on a resource resctrl is unaware of.
>
> Signed-off-by: James Morse<james.morse@arm.com>
> Signed-off-by: Andre Przywara<andre.przywara@arm.com>
> ---
> drivers/acpi/arm64/mpam.c | 91 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 88 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/acpi/arm64/mpam.c b/drivers/acpi/arm64/mpam.c
> index 84963a20c3e7..99c2bdbb3314 100644
> --- a/drivers/acpi/arm64/mpam.c
> +++ b/drivers/acpi/arm64/mpam.c
> @@ -95,17 +95,51 @@ static void acpi_mpam_parse_irqs(struct platform_device *pdev,
> res[(*res_idx)++] = DEFINE_RES_IRQ_NAMED(irq, "error");
> }
>
> -static int acpi_mpam_parse_resource(struct mpam_msc *msc,
> +#define UUID_MPAM_INTERCONNECT_TABLE "fe2bd645-033b-49e6-9479-2e0b8b21d1cd"
> +
> +struct acpi_mpam_interconnect_descriptor_table {
> + u8 type_uuid[16];
> + u32 num_descriptors;
> +};
> +
> +struct acpi_mpam_interconnect_descriptor {
> + u32 source_id;
> + u32 destination_id;
> + u8 link_type;
> + u8 reserved[3];
> +};
> +
> +static int acpi_mpam_parse_resource(struct acpi_mpam_msc_node *tbl_msc,
> + struct mpam_msc *msc,
> struct acpi_mpam_resource_node *res)
> {
> + struct acpi_mpam_interconnect_descriptor_table *tbl_int_tbl;
> + struct acpi_mpam_interconnect_descriptor *tbl_int;
> + guid_t int_tbl_uuid, spec_uuid;
> int level, nid;
> u32 cache_id;
> + off_t offset;
>
> + /*
> + * Class IDs are somewhat arbitrary, but need to be co-ordinated.
> + * 0-N are caches,
> + * 64, 65: Interconnect, but ideally these would appear between the
> + * classes the controls are adjacent to.
> + * 128: SMMU,
> + * 192-192+level: Memory Side Caches, nothing checks that N is a
> + * small number.
> + * 255: Memory Controllers
> + *
> + * ACPI devices would need a class id allocated based on the _HID.
> + *
> + * Classes that the mpam driver can't currently plumb into resctrl
> + * are registered as UNKNOWN.
> + */
> switch (res->locator_type) {
> case ACPI_MPAM_LOCATION_TYPE_PROCESSOR_CACHE:
> cache_id = res->locator.cache_locator.cache_reference;
> level = find_acpi_cache_level_from_id(cache_id);
> - if (level <= 0) {
> + if (level <= 0 || level >= 64) {
> pr_err_once("Bad level (%d) for cache with id %u\n", level, cache_id);
> return -EINVAL;
> }
> @@ -120,6 +154,57 @@ static int acpi_mpam_parse_resource(struct mpam_msc *msc,
> }
> return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_MEMORY,
> MPAM_CLASS_ID_DEFAULT, nid);
> + case ACPI_MPAM_LOCATION_TYPE_SMMU:
> + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_UNKNOWN,
> + 128, res->locator.smmu_locator.smmu_interface);
> + case ACPI_MPAM_LOCATION_TYPE_MEMORY_CACHE:
> + cache_id = res->locator.mem_cache_locator.reference;
> + level = res->locator.mem_cache_locator.level;
> + if (192 + level >= 255) {
> + pr_err_once("Bad level for memory side cache with reference %u\n",
> + cache_id);
> + return -EINVAL;
> + }
> +
> + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_CACHE,
> + 192 + level, cache_id);
> +
> + case ACPI_MPAM_LOCATION_TYPE_INTERCONNECT:
> + /* Find the descriptor table, and check it lands in the parent msc */
> + offset = res->locator.interconnect_ifc_locator.inter_connect_desc_tbl_off;
> + if (offset >= tbl_msc->length) {
> + pr_err_once("Bad offset for interconnect descriptor on msc %u\n",
> + tbl_msc->identifier);
> + return -EINVAL;
> + }
> + tbl_int_tbl = ACPI_ADD_PTR(struct acpi_mpam_interconnect_descriptor_table,
> + tbl_msc, offset);
> + guid_parse(UUID_MPAM_INTERCONNECT_TABLE, &spec_uuid);
> + import_guid(&int_tbl_uuid, tbl_int_tbl->type_uuid);
> + if (guid_equal(&spec_uuid, &int_tbl_uuid)) {
> + pr_err_once("Bad UUID for interconnect descriptor on msc %u\n",
> + tbl_msc->identifier);
> + return -EINVAL;
> +
>
> Looks like the condition seems to be inverted. This currently returns -EINVAL when the UUID matches the expected spec UUID, and accepts mismatched UUIDs.It probably should be:
> if (!guid_equal(&spec_uuid, &int_tbl_uuid)) {
>
>
> + offset += sizeof(*tbl_int_tbl);
> + offset += tbl_int_tbl->num_descriptors * sizeof(*tbl_int);
> + if (offset >= tbl_msc->length) {
> + pr_err_once("Bad num_descriptors for interconnect descriptor on msc %u\n",
> + tbl_msc->identifier);
> + return -EINVAL;
> + }
> +
> + tbl_int = ACPI_ADD_PTR(struct acpi_mpam_interconnect_descriptor,
> + tbl_int_tbl, sizeof(*tbl_int_tbl));
> + cache_id = tbl_int->source_id;
> +
> + /* Unknown link type? */
> + if (tbl_int->link_type != 0 && tbl_int->link_type == 1)
> + return 0;
>
> And here I think != 0 && == 1 simplifies to just == 1, so this drops the valid PROC link type (0x01) while letting any unknown value (≥ 2) fall through to mpam_ris_create with an arbitrary class ID. Per DEN0065B, only 0x00 (NUMA) and 0x01 (PROC) are defined. So it probably should be:
>
> if (tbl_int->link_type != 0 && tbl_int->link_type != 1)
> return 0;
>
> +
> + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_UNKNOWN,
> + 64 + tbl_int->link_type, cache_id);
> default:
> /* These get discovered later and are treated as unknown */
> return 0;
> @@ -150,7 +235,7 @@ int acpi_mpam_parse_resources(struct mpam_msc *msc,
> return -EINVAL;
> }
>
> - err = acpi_mpam_parse_resource(msc, resource);
> + err = acpi_mpam_parse_resource(tbl_msc, msc, resource);
> if (err)
> return err;
>
> Best Regards,
> Srivathsa
^ permalink raw reply
* [PATCH v3 1/8] mm: Add ptep_try_set() for lockless empty-slot installs
From: Tejun Heo @ 2026-05-21 17:37 UTC (permalink / raw)
To: David Vernet, Andrea Righi, Changwoo Min, Alexei Starovoitov,
Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
Kumar Kartikeya Dwivedi
Cc: Peter Zijlstra, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, Andrew Morton,
David Hildenbrand, Mike Rapoport, Emil Tsalapatis, sched-ext, bpf,
x86, linux-arm-kernel, linux-mm, linux-kernel
In-Reply-To: <20260520235052.4180316-2-tj@kernel.org>
Add ptep_try_set(ptep, new_pte): atomically set *ptep to new_pte iff it is
currently pte_none(). Returns true on success, false if the slot was already
populated or the arch has no implementation.
The intended caller is the upcoming bpf_arena kernel-side fault recovery
path. The install runs from a page fault that can be nested under locks
held by the faulting kernel caller (e.g. a BPF program holding
raw_res_spin_lock_irqsave on its arena's spinlock), so trylock-and-retry
would A-A deadlock. Lock-free cmpxchg is the only viable option, which
constrains this helper to special kernel page tables where concurrent
writers cooperate via atomic accessors.
The generic version in <linux/pgtable.h> returns false. x86 and arm64
override with try_cmpxchg-based implementations on the underlying pteval.
Other architectures get the false stub - the callers there already fall
through to oops.
v2: Rename to ptep_try_set(). Tighten kerneldoc. (David, Alexei)
v3: Note that strict-zero cmpxchg is narrower than pte_none(). (Andrea)
Suggested-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
Cc: David Hildenbrand <david@kernel.org>
---
arch/arm64/include/asm/pgtable.h | 8 ++++++++
arch/x86/include/asm/pgtable.h | 12 ++++++++++++
include/linux/pgtable.h | 25 +++++++++++++++++++++++++
3 files changed, 45 insertions(+)
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -1830,6 +1830,14 @@ static inline pte_t ptep_get_and_clear(s
return __ptep_get_and_clear(mm, addr, ptep);
}
+static inline bool ptep_try_set(pte_t *ptep, pte_t new_pte)
+{
+ pteval_t old = 0;
+
+ return try_cmpxchg(&pte_val(*ptep), &old, pte_val(new_pte));
+}
+#define ptep_try_set ptep_try_set
+
#define test_and_clear_young_ptes test_and_clear_young_ptes
static inline bool test_and_clear_young_ptes(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep, unsigned int nr)
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1284,6 +1284,18 @@ static inline void ptep_set_wrprotect(st
} while (!try_cmpxchg((long *)&ptep->pte, (long *)&old_pte, *(long *)&new_pte));
}
+/*
+ * Note: strictly-zero compare is narrower than pte_none(), but the gap is
+ * harmless: _PAGE_DIRTY and _PAGE_ACCESSED aren't set on untouched kernel PTEs.
+ */
+static inline bool ptep_try_set(pte_t *ptep, pte_t new_pte)
+{
+ pte_t old_pte = __pte(0);
+
+ return try_cmpxchg((long *)&ptep->pte, (long *)&old_pte, *(long *)&new_pte);
+}
+#define ptep_try_set ptep_try_set
+
#define flush_tlb_fix_spurious_fault(vma, address, ptep) do { } while (0)
#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -1036,6 +1036,31 @@ static inline void ptep_set_wrprotect(st
}
#endif
+#ifndef ptep_try_set
+/**
+ * ptep_try_set - atomically set an empty kernel PTE
+ * @ptep: page table entry
+ * @new_pte: value to install
+ *
+ * Atomically set *@ptep to @new_pte iff *@ptep is pte_none(). Return true on
+ * success, false if the slot was already populated or the arch has no
+ * implementation.
+ *
+ * For special kernel page tables only - never user page tables. The caller must
+ * prevent concurrent teardown of @ptep and must accept that other writers may
+ * race. Concurrent clearers must use ptep_get_and_clear() so racing accesses
+ * agree on the outcome.
+ *
+ * Architectures opt in by providing a cmpxchg-based override and defining
+ * ptep_try_set as an identity macro. The generic stub returns false, which is
+ * correct for callers that fall through to oops on failure.
+ */
+static inline bool ptep_try_set(pte_t *ptep, pte_t new_pte)
+{
+ return false;
+}
+#endif
+
#ifndef wrprotect_ptes
/**
* wrprotect_ptes - Write-protect PTEs that map consecutive pages of the same
^ permalink raw reply
* [PATCH v2 7/8] sched_ext: Sub-allocator over kernel-claimed BPF arena pages
From: Tejun Heo @ 2026-05-21 17:37 UTC (permalink / raw)
To: David Vernet, Andrea Righi, Changwoo Min, Alexei Starovoitov,
Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
Kumar Kartikeya Dwivedi
Cc: Peter Zijlstra, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, Andrew Morton,
David Hildenbrand, Mike Rapoport, Emil Tsalapatis, sched-ext, bpf,
x86, linux-arm-kernel, linux-mm, linux-kernel
In-Reply-To: <20260520235052.4180316-8-tj@kernel.org>
Build a per-scheduler sub-allocator on top of pages claimed from the BPF
arena registered in the previous patch. Subsequent kernel-managed
arena-resident structures (e.g. per-CPU set_cmask cmask) carve their storage
from this pool.
scx_arena_pool_init() creates a gen_pool. scx_arena_alloc() returns the
kernel VA. On exhaustion, the pool grows by claiming more pages via
bpf_arena_alloc_pages_sleepable(). Chunks are added at the kernel-side
mapping address; callers translate to the BPF-arena form themselves if
needed.
Allocations sleep (GFP_KERNEL) - they may grow the pool through vzalloc and
arena page allocation. All current consumers run from the enable path (after
ops.init() and the kernel-side arena auto-discovery, before validate_ops()),
where sleeping is fine.
scx_arena_pool_destroy() walks each chunk, returns outstanding ranges to the
gen_pool with gen_pool_free() and then calls gen_pool_destroy(). The
underlying arena pages are released when the arena map itself is torn down,
so the pool destroy doesn't free them explicitly.
v2: Switch scx_arena_alloc() to a loop. (Andrea)
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Andrea Righi <arighi@nvidia.com>
---
kernel/sched/build_policy.c | 4 +
kernel/sched/ext.c | 11 +++
kernel/sched/ext_arena.c | 126 ++++++++++++++++++++++++++++++++++++++++++++
kernel/sched/ext_arena.h | 18 ++++++
kernel/sched/ext_internal.h | 5 +
5 files changed, 164 insertions(+)
--- a/kernel/sched/build_policy.c
+++ b/kernel/sched/build_policy.c
@@ -59,12 +59,16 @@
#ifdef CONFIG_SCHED_CLASS_EXT
# include <linux/btf_ids.h>
+# include <linux/find.h>
+# include <linux/genalloc.h>
# include "ext_types.h"
# include "ext_internal.h"
# include "ext_cid.h"
+# include "ext_arena.h"
# include "ext_idle.h"
# include "ext.c"
# include "ext_cid.c"
+# include "ext_arena.c"
# include "ext_idle.c"
#endif
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -5003,6 +5003,7 @@ static void scx_sched_free_rcu_work(stru
rhashtable_free_and_destroy(&sch->dsq_hash, NULL, NULL);
free_exit_info(sch->exit_info);
+ scx_arena_pool_destroy(sch);
if (sch->arena_map)
bpf_map_put(sch->arena_map);
kfree(sch);
@@ -7155,6 +7156,12 @@ static void scx_root_enable_workfn(struc
sch->exit_info->flags |= SCX_EFLAG_INITIALIZED;
}
+ ret = scx_arena_pool_init(sch);
+ if (ret) {
+ cpus_read_unlock();
+ goto err_disable;
+ }
+
for (i = SCX_OPI_CPU_HOTPLUG_BEGIN; i < SCX_OPI_CPU_HOTPLUG_END; i++)
if (((void (**)(void))ops)[i])
set_bit(i, sch->has_op);
@@ -7473,6 +7480,10 @@ static void scx_sub_enable_workfn(struct
sch->exit_info->flags |= SCX_EFLAG_INITIALIZED;
}
+ ret = scx_arena_pool_init(sch);
+ if (ret)
+ goto err_disable;
+
if (validate_ops(sch, ops))
goto err_disable;
--- /dev/null
+++ b/kernel/sched/ext_arena.c
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * BPF extensible scheduler class: Documentation/scheduler/sched-ext.rst
+ *
+ * scx_arena_pool: kernel-side sub-allocator over BPF-arena pages.
+ *
+ * Each chunk added to @sch->arena_pool comes from one
+ * bpf_arena_alloc_pages_sleepable() call and is registered at the
+ * kernel-side mapping address. Callers translate to the BPF-arena form
+ * themselves if needed.
+ *
+ * Allocations grow the pool on demand. Underlying arena pages are released
+ * when the arena map itself is torn down.
+ *
+ * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
+ * Copyright (c) 2026 Tejun Heo <tj@kernel.org>
+ */
+
+enum scx_arena_consts {
+ SCX_ARENA_MIN_ORDER = 3, /* 8-byte minimum sub-allocation */
+ SCX_ARENA_GROW_PAGES = 4, /* per growth */
+};
+
+s32 scx_arena_pool_init(struct scx_sched *sch)
+{
+ if (!sch->arena_map)
+ return 0;
+
+ sch->arena_pool = gen_pool_create(SCX_ARENA_MIN_ORDER, NUMA_NO_NODE);
+ if (!sch->arena_pool)
+ return -ENOMEM;
+ return 0;
+}
+
+static void scx_arena_clear_chunk(struct gen_pool *pool, struct gen_pool_chunk *chunk,
+ void *data)
+{
+ int order = pool->min_alloc_order;
+ size_t chunk_sz = chunk->end_addr - chunk->start_addr + 1;
+ unsigned long end_bit = chunk_sz >> order;
+ unsigned long b, e;
+
+ for_each_set_bitrange(b, e, chunk->bits, end_bit)
+ gen_pool_free(pool, chunk->start_addr + (b << order),
+ (e - b) << order);
+}
+
+/*
+ * Tear down the pool. Outstanding gen_pool allocations are freed via
+ * scx_arena_clear_chunk() so gen_pool_destroy() doesn't BUG. The underlying
+ * arena pages are released when the arena map itself is torn down.
+ */
+void scx_arena_pool_destroy(struct scx_sched *sch)
+{
+ if (!sch->arena_pool)
+ return;
+ gen_pool_for_each_chunk(sch->arena_pool, scx_arena_clear_chunk, NULL);
+ gen_pool_destroy(sch->arena_pool);
+ sch->arena_pool = NULL;
+}
+
+/*
+ * Grow the pool by @page_cnt pages. bpf_arena_alloc_pages_sleepable() and
+ * gen_pool_add() (which calls vzalloc(GFP_KERNEL)) require a sleepable
+ * context.
+ */
+static int scx_arena_grow(struct scx_sched *sch, u32 page_cnt)
+{
+ u64 kern_vm_start;
+ u32 uaddr32;
+ void *p;
+ int ret;
+
+ if (!sch->arena_map || !sch->arena_pool)
+ return -EINVAL;
+
+ p = bpf_arena_alloc_pages_sleepable(sch->arena_map, NULL,
+ page_cnt, NUMA_NO_NODE, 0);
+ if (!p)
+ return -ENOMEM;
+
+ uaddr32 = (u32)(unsigned long)p;
+ kern_vm_start = bpf_arena_map_kern_vm_start(sch->arena_map);
+
+ ret = gen_pool_add(sch->arena_pool, kern_vm_start + uaddr32,
+ page_cnt * PAGE_SIZE, NUMA_NO_NODE);
+ if (ret) {
+ bpf_arena_free_pages_non_sleepable(sch->arena_map, p, page_cnt);
+ return ret;
+ }
+ return 0;
+}
+
+/*
+ * Allocate @size bytes from the arena pool. Returns kernel VA on success, NULL
+ * on failure. May grow the pool via scx_arena_grow() which sleeps. Caller must
+ * be in a GFP_KERNEL context.
+ */
+void *scx_arena_alloc(struct scx_sched *sch, size_t size)
+{
+ unsigned long kern_va;
+ u32 page_cnt;
+
+ might_sleep();
+
+ if (!sch->arena_pool)
+ return NULL;
+
+ while (true) {
+ kern_va = gen_pool_alloc(sch->arena_pool, size);
+ if (kern_va)
+ break;
+ page_cnt = max_t(u32, SCX_ARENA_GROW_PAGES,
+ (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ if (scx_arena_grow(sch, page_cnt))
+ return NULL;
+ }
+
+ return (void *)kern_va;
+}
+
+void scx_arena_free(struct scx_sched *sch, void *kern_va, size_t size)
+{
+ if (sch->arena_pool && kern_va)
+ gen_pool_free(sch->arena_pool, (unsigned long)kern_va, size);
+}
--- /dev/null
+++ b/kernel/sched/ext_arena.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * BPF extensible scheduler class: Documentation/scheduler/sched-ext.rst
+ *
+ * Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
+ * Copyright (c) 2025 Tejun Heo <tj@kernel.org>
+ */
+#ifndef _KERNEL_SCHED_EXT_ARENA_H
+#define _KERNEL_SCHED_EXT_ARENA_H
+
+struct scx_sched;
+
+s32 scx_arena_pool_init(struct scx_sched *sch);
+void scx_arena_pool_destroy(struct scx_sched *sch);
+void *scx_arena_alloc(struct scx_sched *sch, size_t size);
+void scx_arena_free(struct scx_sched *sch, void *kern_va, size_t size);
+
+#endif /* _KERNEL_SCHED_EXT_ARENA_H */
--- a/kernel/sched/ext_internal.h
+++ b/kernel/sched/ext_internal.h
@@ -1116,8 +1116,13 @@ struct scx_sched {
* Arena map auto-discovered from member progs at struct_ops attach.
* cid-form schedulers must use exactly one arena across all member
* progs. NULL on cpu-form.
+ *
+ * @arena_pool sub-allocates @arena_map. Each gen_pool chunk is added
+ * at the kernel-side mapping address. Grows on demand and pages are
+ * not released until sched destroy.
*/
struct bpf_map *arena_map;
+ struct gen_pool *arena_pool;
DECLARE_BITMAP(has_op, SCX_OPI_END);
^ permalink raw reply
* Re: [PATCH 2/8] bpf: Recover arena kernel faults with scratch page
From: Tejun Heo @ 2026-05-21 17:39 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: David Vernet, Andrea Righi, Changwoo Min, Alexei Starovoitov,
Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
Kumar Kartikeya Dwivedi, Peter Zijlstra, Catalin Marinas,
Will Deacon, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, Andrew Morton, David Hildenbrand, Mike Rapoport,
Emil Tsalapatis, sched-ext, bpf, x86, linux-arm-kernel, linux-mm,
linux-kernel
In-Reply-To: <DIO99FYEHNC1.23KFEHRPTRB5N@gmail.com>
On Thu, May 21, 2026 at 02:42:50AM -0700, Alexei Starovoitov wrote:
> On Wed May 20, 2026 at 4:50 PM PDT, Tejun Heo wrote:
> First 5 patches lgtm. Should we create a stable branch out of them
> and pull into bpf-next and sched-ext trees?
> I'm preparing a followup for slab-over-arena on top of these changes.
I just posted a new version of the first patch w/ comment update. It'd be
great if we can make forward progress.
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH 1/2] gfp_types: Introduce a new GFP_ATOMIC_RT gfp flag
From: Waiman Long @ 2026-05-21 17:40 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: Marc Zyngier, Thomas Gleixner, Sebastian Andrzej Siewior,
Clark Williams, Steven Rostedt, Andrew Morton, David Hildenbrand,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, linux-arm-kernel, linux-kernel,
linux-mm, linux-rt-devel, Matthew Wilcox
In-Reply-To: <ag8zX5KJUKo70TvG@lucifer>
On 5/21/26 12:40 PM, Lorenzo Stoakes wrote:
> +cc Matthew who has fairly strong opinions on GFP flags and such :)
>
> Also, please don't send 2 patch series with 2/2 in-reply-to 1/2, use a
> cover letter + have patches reply to that :) [yes it's one of those
> subjective things that people differ on a lot but generally how we do in
> mm]
>
> On Wed, May 20, 2026 at 04:46:27PM -0400, Waiman Long wrote:
>> The GFP_ATOMIC flag is to be used in atomic context where user cannot
>> sleep and need the allocation to succeed. However, it does not support
>> contexts where preemption or interrupt is disabled under PREEMPT_RT
>> like raw_spin_lock_irqsave() or plain preempt_disable().
>>
>> With the advance of the ALLOC_TRYLOCK allocation flag in the v7.1
>> kernel, it is possible to allocate memory under such contexts by using
>> spin_trylock to acquire the spinlock in the memory allocation path. This
>> does increase the chance that the allocation can fail due to the presence
>> of concurrent memory allocation requests. So its users must be able to
>> handle such memory allocation failure gracefully.
>>
>> The ALLOC_TRYLOCK flag will only be enabled if none of the
>> ___GFP_DIRECT_RECLAIM and ___GFP_KSWAPD_RECLAIM flags are set.
>>
>> Introduce a new GFP_ATOMIC_RT gfp flag for those PREEMPT_RT
>> atomic contexts. This new flag will fall back to GFP_ATOMIC in
>> non-PREEMPT_RT kernel. GFP_ATOMIC can continue to be used in contexts
>> where preemption and interrupt are not disabled in PREEMPT_RT kernel
>> like spin_lock_irqsave().
> This seems like the wrong place for the solution, now we have to remember
> to use a specific GFP flag but only in one specific place in some IRQ code,
> yet RT is fine with this in any other scenario?
>
> This is really confusing.
>
> Wouldn't we better off with a way of actively detecting this context
> somehow in the page allocator?
This new GFP_ATOMIC_RT flag will make memory allocation more likely to
fail compared with GFP_ATOMIC. That is the main reason why I think a
separate flag with documentation about this difference will make the
users of the new gfp flag more aware of what they should check before
they use it.
I would certainly like to have the mm memory allocation code to handle
it automatically if it doesn't impact the failure rate.
>
> It just instinctively feels like this is the wrong level of abstraction for
> a fix here :)
With PREEMPT_RT, GFP_ATOMIC_RT just translates to __GFP_HIGH. It can be
set explicitly in the relevant call sites. This patch is more a
documentation step to make clear the purpose and consequence of doing that.
>
>> Signed-off-by: Waiman Long <longman@redhat.com>
>> ---
>> include/linux/gfp_types.h | 13 +++++++++++++
>> 1 file changed, 13 insertions(+)
>>
>> diff --git a/include/linux/gfp_types.h b/include/linux/gfp_types.h
>> index cd4972a7c97c..ac30882b6cd4 100644
>> --- a/include/linux/gfp_types.h
>> +++ b/include/linux/gfp_types.h
>> @@ -316,6 +316,13 @@ enum {
>> * preempt_disable() - see "Memory allocation" in
>> * Documentation/core-api/real-time/differences.rst for more info.
>> *
>> + * %GFP_ATOMIC_RT is similar to %GFP_ATOMIC with the addition that it can also
>> + * be used in context where preemption and/or interrupt is disabled under
>> + * PREEMPT_RT, but not in NMI or hardirq contexts. The allocation is more
> I'm not sure 'GFP_ATOMIC_RT' really communicates all of this information.
I am not good at naming. If you have other good suggestion, I would like
to hear it.
Cheers,
Longman
^ permalink raw reply
* Re: [PATCH v5 3/3] iommu/arm-smmu-v3: Allow ATS to be always on
From: Nicolin Chen @ 2026-05-21 17:44 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: will, joro, bhelgaas, robin.murphy, praan, baolu.lu, kevin.tian,
miko.lenczewski, linux-arm-kernel, iommu, linux-kernel, linux-pci,
dan.j.williams, jonathan.cameron, vsethi, linux-cxl, nirmoyd
In-Reply-To: <20260521134409.GG3602937@nvidia.com>
On Thu, May 21, 2026 at 10:44:09AM -0300, Jason Gunthorpe wrote:
> On Wed, May 20, 2026 at 03:35:32PM -0700, Nicolin Chen wrote:
> > @ -3870,13 +3870,15 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,
> > * When the last user of the CD table goes away downgrade the STE back
> > * to a non-cd_table one, by re-attaching its sid_domain.
> > */
> > - if (!master->ats_always_on &&
> > - !arm_smmu_ssids_in_use(&master->cd_table)) {
> > + if (!arm_smmu_ssids_in_use(&master->cd_table)) {
> > struct iommu_domain *sid_domain =
> > iommu_driver_get_domain_for_dev(master->dev);
> > + bool ats_always_on = master->ats_always_on &&
> > + sid_domain->type != IOMMU_DOMAIN_BLOCKED;
> > + bool downgrade = sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
> > + sid_domain->type == IOMMU_DOMAIN_BLOCKED;
> >
> > - if (sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
> > - sid_domain->type == IOMMU_DOMAIN_BLOCKED)
> > + if (!ats_always_on && downgrade)
> > sid_domain->ops->attach_dev(sid_domain, dev,
> > sid_domain);
>
> Only identity should remain with the CD S1DSS STE, BLOCKED should
> attach the normal blocking domain still
Yea. I have !ats_always_on guarding here.
Thanks
Nicolin
^ permalink raw reply
* Re: [PATCH v2 2/2] remoteproc: xlnx: enable auto boot feature
From: Mathieu Poirier @ 2026-05-21 17:48 UTC (permalink / raw)
To: Tanmay Shah
Cc: andersson, robh, krzk+dt, conor+dt, michal.simek, ben.levinsky,
linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260501143707.1591110-3-tanmay.shah@amd.com>
Good morning,
I don't recal reviewing the first revision of this set. Can you provide a link
to it so that I can read the comments that were provided?
On Fri, May 01, 2026 at 07:37:07AM -0700, Tanmay Shah wrote:
> remoteproc framework has capability to start (or attach to) the remote
The remoteproc framework...
> processor automatically if auto boot flag is set by the driver during
> probe. If remote core is not started before the Linux boot, and linux is
> expected to start the remote core then it uses "firmware-name" property
> to load default firmware during auto boot.
>
> Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
> ---
> drivers/remoteproc/xlnx_r5_remoteproc.c | 48 +++++++++++++++++--------
> 1 file changed, 34 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
> index 45a62cb98072..652030f9cea2 100644
> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
> @@ -899,17 +899,18 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = {
> };
>
> /**
> - * zynqmp_r5_add_rproc_core() - Add core data to framework.
> - * Allocate and add struct rproc object for each r5f core
> + * zynqmp_r5_alloc_rproc_core() - alloc rproc core data structure
> + * Allocate struct rproc object for each r5f core
> * This is called for each individual r5f core
> *
> * @cdev: Device node of each r5 core
> *
> * Return: zynqmp_r5_core object for success else error code pointer
> */
> -static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
> +static struct zynqmp_r5_core *zynqmp_r5_alloc_rproc_core(struct device *cdev)
Why is there a need to change the function's name?
> {
> struct zynqmp_r5_core *r5_core;
> + const char *fw_name = NULL;
> struct rproc *r5_rproc;
> int ret;
>
> @@ -918,10 +919,15 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
> if (ret)
> return ERR_PTR(ret);
>
> + ret = rproc_of_parse_firmware(cdev, 0, &fw_name);
> + if (ret < 0 && ret != -EINVAL)
> + return ERR_PTR(dev_err_probe(cdev, ret,
> + "failed to parse firmware-name\n"));
> +
> /* Allocate remoteproc instance */
> r5_rproc = rproc_alloc(cdev, dev_name(cdev),
> &zynqmp_r5_rproc_ops,
> - NULL, sizeof(struct zynqmp_r5_core));
> + fw_name, sizeof(struct zynqmp_r5_core));
> if (!r5_rproc) {
> dev_err(cdev, "failed to allocate memory for rproc instance\n");
> return ERR_PTR(-ENOMEM);
> @@ -932,6 +938,11 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
> r5_rproc->recovery_disabled = true;
> r5_rproc->has_iommu = false;
> r5_rproc->auto_boot = false;
> +
> + /* attempt to boot automatically if the firmware-name is provided */
> + if (fw_name)
> + r5_rproc->auto_boot = true;
> +
What happens when a firmware name needs to be provided in the DT but you don't
want to automatically boot the remote processor?
> r5_core = r5_rproc->priv;
> r5_core->dev = cdev;
> r5_core->np = dev_of_node(cdev);
> @@ -941,13 +952,6 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
> goto free_rproc;
> }
>
> - /* Add R5 remoteproc core */
> - ret = rproc_add(r5_rproc);
> - if (ret) {
> - dev_err(cdev, "failed to add r5 remoteproc\n");
> - goto free_rproc;
> - }
> -
I'm not sure why there is a need to move this to zynqmp_r5_cluster_init()? Is
it simply to make the error path easier to handle? If so, please do that in a
separate patch.
> r5_core->rproc = r5_rproc;
> return r5_core;
>
> @@ -1280,6 +1284,7 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
> if (zynqmp_r5_get_rsc_table_va(r5_core))
> dev_dbg(r5_core->dev, "rsc tbl not found\n");
> r5_core->rproc->state = RPROC_DETACHED;
> + r5_core->rproc->auto_boot = true;
I thought this was done in zynqmp_r5_add_rproc_core() - what am I missing?
Thanks,
Mathieu
> }
> }
>
> @@ -1304,7 +1309,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
> enum rpu_oper_mode fw_reg_val;
> struct device **child_devs;
> enum rpu_tcm_comb tcm_mode;
> - int core_count, ret, i;
> + int core_count, ret, i, j;
> struct mbox_info *ipi;
>
> ret = of_property_read_u32(dev_node, "xlnx,cluster-mode", &cluster_mode);
> @@ -1390,7 +1395,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
> child_devs[i] = &child_pdev->dev;
>
> /* create and add remoteproc instance of type struct rproc */
> - r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev);
> + r5_cores[i] = zynqmp_r5_alloc_rproc_core(&child_pdev->dev);
> if (IS_ERR(r5_cores[i])) {
> ret = PTR_ERR(r5_cores[i]);
> r5_cores[i] = NULL;
> @@ -1435,16 +1440,31 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
> goto release_r5_cores;
> }
>
> + for (j = 0; j < cluster->core_count; j++) {
> + /* Add R5 remoteproc core */
> + ret = rproc_add(r5_cores[j]->rproc);
> + if (ret) {
> + dev_err_probe(r5_cores[j]->dev, ret,
> + "failed to add remoteproc\n");
> + goto delete_r5_cores;
> + }
> + }
> +
> kfree(child_devs);
> return 0;
>
> +delete_r5_cores:
> + i = core_count - 1;
> + /* delete previous added rproc */
> + while (--j >= 0)
> + rproc_del(r5_cores[j]->rproc);
> +
> release_r5_cores:
> while (i >= 0) {
> put_device(child_devs[i]);
> if (r5_cores[i]) {
> zynqmp_r5_free_mbox(r5_cores[i]->ipi);
> of_reserved_mem_device_release(r5_cores[i]->dev);
> - rproc_del(r5_cores[i]->rproc);
> rproc_free(r5_cores[i]->rproc);
> }
> i--;
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v2 7/8] sched_ext: Sub-allocator over kernel-claimed BPF arena pages
From: Andrea Righi @ 2026-05-21 17:54 UTC (permalink / raw)
To: Tejun Heo
Cc: David Vernet, Changwoo Min, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Peter Zijlstra, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, Andrew Morton,
David Hildenbrand, Mike Rapoport, Emil Tsalapatis, sched-ext, bpf,
x86, linux-arm-kernel, linux-mm, linux-kernel
In-Reply-To: <dd5b3702a826666242b6eb6e805bf83f@kernel.org>
On Thu, May 21, 2026 at 07:37:46AM -1000, Tejun Heo wrote:
> Build a per-scheduler sub-allocator on top of pages claimed from the BPF
> arena registered in the previous patch. Subsequent kernel-managed
> arena-resident structures (e.g. per-CPU set_cmask cmask) carve their storage
> from this pool.
>
> scx_arena_pool_init() creates a gen_pool. scx_arena_alloc() returns the
> kernel VA. On exhaustion, the pool grows by claiming more pages via
> bpf_arena_alloc_pages_sleepable(). Chunks are added at the kernel-side
> mapping address; callers translate to the BPF-arena form themselves if
> needed.
>
> Allocations sleep (GFP_KERNEL) - they may grow the pool through vzalloc and
> arena page allocation. All current consumers run from the enable path (after
> ops.init() and the kernel-side arena auto-discovery, before validate_ops()),
> where sleeping is fine.
>
> scx_arena_pool_destroy() walks each chunk, returns outstanding ranges to the
> gen_pool with gen_pool_free() and then calls gen_pool_destroy(). The
> underlying arena pages are released when the arena map itself is torn down,
> so the pool destroy doesn't free them explicitly.
>
> v2: Switch scx_arena_alloc() to a loop. (Andrea)
>
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: Andrea Righi <arighi@nvidia.com>
Looks good to me.
Reviewed-by: Andrea Righi <arighi@nvidia.com>
Thanks,
-Andrea
> ---
> kernel/sched/build_policy.c | 4 +
> kernel/sched/ext.c | 11 +++
> kernel/sched/ext_arena.c | 126 ++++++++++++++++++++++++++++++++++++++++++++
> kernel/sched/ext_arena.h | 18 ++++++
> kernel/sched/ext_internal.h | 5 +
> 5 files changed, 164 insertions(+)
>
> --- a/kernel/sched/build_policy.c
> +++ b/kernel/sched/build_policy.c
> @@ -59,12 +59,16 @@
>
> #ifdef CONFIG_SCHED_CLASS_EXT
> # include <linux/btf_ids.h>
> +# include <linux/find.h>
> +# include <linux/genalloc.h>
> # include "ext_types.h"
> # include "ext_internal.h"
> # include "ext_cid.h"
> +# include "ext_arena.h"
> # include "ext_idle.h"
> # include "ext.c"
> # include "ext_cid.c"
> +# include "ext_arena.c"
> # include "ext_idle.c"
> #endif
>
> --- a/kernel/sched/ext.c
> +++ b/kernel/sched/ext.c
> @@ -5003,6 +5003,7 @@ static void scx_sched_free_rcu_work(stru
>
> rhashtable_free_and_destroy(&sch->dsq_hash, NULL, NULL);
> free_exit_info(sch->exit_info);
> + scx_arena_pool_destroy(sch);
> if (sch->arena_map)
> bpf_map_put(sch->arena_map);
> kfree(sch);
> @@ -7155,6 +7156,12 @@ static void scx_root_enable_workfn(struc
> sch->exit_info->flags |= SCX_EFLAG_INITIALIZED;
> }
>
> + ret = scx_arena_pool_init(sch);
> + if (ret) {
> + cpus_read_unlock();
> + goto err_disable;
> + }
> +
> for (i = SCX_OPI_CPU_HOTPLUG_BEGIN; i < SCX_OPI_CPU_HOTPLUG_END; i++)
> if (((void (**)(void))ops)[i])
> set_bit(i, sch->has_op);
> @@ -7473,6 +7480,10 @@ static void scx_sub_enable_workfn(struct
> sch->exit_info->flags |= SCX_EFLAG_INITIALIZED;
> }
>
> + ret = scx_arena_pool_init(sch);
> + if (ret)
> + goto err_disable;
> +
> if (validate_ops(sch, ops))
> goto err_disable;
>
> --- /dev/null
> +++ b/kernel/sched/ext_arena.c
> @@ -0,0 +1,126 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * BPF extensible scheduler class: Documentation/scheduler/sched-ext.rst
> + *
> + * scx_arena_pool: kernel-side sub-allocator over BPF-arena pages.
> + *
> + * Each chunk added to @sch->arena_pool comes from one
> + * bpf_arena_alloc_pages_sleepable() call and is registered at the
> + * kernel-side mapping address. Callers translate to the BPF-arena form
> + * themselves if needed.
> + *
> + * Allocations grow the pool on demand. Underlying arena pages are released
> + * when the arena map itself is torn down.
> + *
> + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
> + * Copyright (c) 2026 Tejun Heo <tj@kernel.org>
> + */
> +
> +enum scx_arena_consts {
> + SCX_ARENA_MIN_ORDER = 3, /* 8-byte minimum sub-allocation */
> + SCX_ARENA_GROW_PAGES = 4, /* per growth */
> +};
> +
> +s32 scx_arena_pool_init(struct scx_sched *sch)
> +{
> + if (!sch->arena_map)
> + return 0;
> +
> + sch->arena_pool = gen_pool_create(SCX_ARENA_MIN_ORDER, NUMA_NO_NODE);
> + if (!sch->arena_pool)
> + return -ENOMEM;
> + return 0;
> +}
> +
> +static void scx_arena_clear_chunk(struct gen_pool *pool, struct gen_pool_chunk *chunk,
> + void *data)
> +{
> + int order = pool->min_alloc_order;
> + size_t chunk_sz = chunk->end_addr - chunk->start_addr + 1;
> + unsigned long end_bit = chunk_sz >> order;
> + unsigned long b, e;
> +
> + for_each_set_bitrange(b, e, chunk->bits, end_bit)
> + gen_pool_free(pool, chunk->start_addr + (b << order),
> + (e - b) << order);
> +}
> +
> +/*
> + * Tear down the pool. Outstanding gen_pool allocations are freed via
> + * scx_arena_clear_chunk() so gen_pool_destroy() doesn't BUG. The underlying
> + * arena pages are released when the arena map itself is torn down.
> + */
> +void scx_arena_pool_destroy(struct scx_sched *sch)
> +{
> + if (!sch->arena_pool)
> + return;
> + gen_pool_for_each_chunk(sch->arena_pool, scx_arena_clear_chunk, NULL);
> + gen_pool_destroy(sch->arena_pool);
> + sch->arena_pool = NULL;
> +}
> +
> +/*
> + * Grow the pool by @page_cnt pages. bpf_arena_alloc_pages_sleepable() and
> + * gen_pool_add() (which calls vzalloc(GFP_KERNEL)) require a sleepable
> + * context.
> + */
> +static int scx_arena_grow(struct scx_sched *sch, u32 page_cnt)
> +{
> + u64 kern_vm_start;
> + u32 uaddr32;
> + void *p;
> + int ret;
> +
> + if (!sch->arena_map || !sch->arena_pool)
> + return -EINVAL;
> +
> + p = bpf_arena_alloc_pages_sleepable(sch->arena_map, NULL,
> + page_cnt, NUMA_NO_NODE, 0);
> + if (!p)
> + return -ENOMEM;
> +
> + uaddr32 = (u32)(unsigned long)p;
> + kern_vm_start = bpf_arena_map_kern_vm_start(sch->arena_map);
> +
> + ret = gen_pool_add(sch->arena_pool, kern_vm_start + uaddr32,
> + page_cnt * PAGE_SIZE, NUMA_NO_NODE);
> + if (ret) {
> + bpf_arena_free_pages_non_sleepable(sch->arena_map, p, page_cnt);
> + return ret;
> + }
> + return 0;
> +}
> +
> +/*
> + * Allocate @size bytes from the arena pool. Returns kernel VA on success, NULL
> + * on failure. May grow the pool via scx_arena_grow() which sleeps. Caller must
> + * be in a GFP_KERNEL context.
> + */
> +void *scx_arena_alloc(struct scx_sched *sch, size_t size)
> +{
> + unsigned long kern_va;
> + u32 page_cnt;
> +
> + might_sleep();
> +
> + if (!sch->arena_pool)
> + return NULL;
> +
> + while (true) {
> + kern_va = gen_pool_alloc(sch->arena_pool, size);
> + if (kern_va)
> + break;
> + page_cnt = max_t(u32, SCX_ARENA_GROW_PAGES,
> + (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
> + if (scx_arena_grow(sch, page_cnt))
> + return NULL;
> + }
> +
> + return (void *)kern_va;
> +}
> +
> +void scx_arena_free(struct scx_sched *sch, void *kern_va, size_t size)
> +{
> + if (sch->arena_pool && kern_va)
> + gen_pool_free(sch->arena_pool, (unsigned long)kern_va, size);
> +}
> --- /dev/null
> +++ b/kernel/sched/ext_arena.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * BPF extensible scheduler class: Documentation/scheduler/sched-ext.rst
> + *
> + * Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
> + * Copyright (c) 2025 Tejun Heo <tj@kernel.org>
> + */
> +#ifndef _KERNEL_SCHED_EXT_ARENA_H
> +#define _KERNEL_SCHED_EXT_ARENA_H
> +
> +struct scx_sched;
> +
> +s32 scx_arena_pool_init(struct scx_sched *sch);
> +void scx_arena_pool_destroy(struct scx_sched *sch);
> +void *scx_arena_alloc(struct scx_sched *sch, size_t size);
> +void scx_arena_free(struct scx_sched *sch, void *kern_va, size_t size);
> +
> +#endif /* _KERNEL_SCHED_EXT_ARENA_H */
> --- a/kernel/sched/ext_internal.h
> +++ b/kernel/sched/ext_internal.h
> @@ -1116,8 +1116,13 @@ struct scx_sched {
> * Arena map auto-discovered from member progs at struct_ops attach.
> * cid-form schedulers must use exactly one arena across all member
> * progs. NULL on cpu-form.
> + *
> + * @arena_pool sub-allocates @arena_map. Each gen_pool chunk is added
> + * at the kernel-side mapping address. Grows on demand and pages are
> + * not released until sched destroy.
> */
> struct bpf_map *arena_map;
> + struct gen_pool *arena_pool;
>
> DECLARE_BITMAP(has_op, SCX_OPI_END);
>
^ permalink raw reply
* [PATCH] media: bcm2835-unicam: Fix log status runtime access
From: Eugen Hristev @ 2026-05-21 18:09 UTC (permalink / raw)
To: Raspberry Pi Kernel Maintenance, Mauro Carvalho Chehab,
Florian Fainelli, Broadcom internal kernel review list, Ray Jui,
Scott Branden, Dave Stevenson, Hans Verkuil, Laurent Pinchart,
Sakari Ailus, Jean-Michel Hautbois
Cc: Naushir Patuck, linux-media, linux-rpi-kernel, linux-arm-kernel,
linux-kernel, Eugen Hristev
When requesting log status, the block might be powered
off, but registers are being read.
Avoid reading the registers if the device is not
resumed, thus also avoid powering up the device just
for log status.
Fixes: 392cd78d495f ("media: bcm2835-unicam: Add support for CCP2/CSI2 camera interface")
Signed-off-by: Eugen Hristev <ehristev@kernel.org>
---
drivers/media/platform/broadcom/bcm2835-unicam.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
index 8d28ba0b59a3..818694f007e2 100644
--- a/drivers/media/platform/broadcom/bcm2835-unicam.c
+++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
@@ -2052,6 +2052,10 @@ static int unicam_log_status(struct file *file, void *fh)
node->fmt.fmt.pix.width, node->fmt.fmt.pix.height);
dev_info(unicam->dev, "V4L2 format: %08x\n",
node->fmt.fmt.pix.pixelformat);
+
+ if (!pm_runtime_get_if_in_use(unicam->dev))
+ return 0;
+
reg = unicam_reg_read(unicam, UNICAM_IPIPE);
dev_info(unicam->dev, "Unpacking/packing: %u / %u\n",
unicam_get_field(reg, UNICAM_PUM_MASK),
---
base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
change-id: 20260521-bcmpipm-6c578e73239c
Best regards,
--
Eugen Hristev <ehristev@kernel.org>
^ permalink raw reply related
* Re: [PATCH v2 2/2] remoteproc: xlnx: enable auto boot feature
From: Shah, Tanmay @ 2026-05-21 18:38 UTC (permalink / raw)
To: Mathieu Poirier, Tanmay Shah
Cc: andersson, robh, krzk+dt, conor+dt, michal.simek, ben.levinsky,
linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <ag9FcXeIIiJWdld7@p14s>
Hello,
Thank you for the reviews, please find my comments below:
On 5/21/2026 12:48 PM, Mathieu Poirier wrote:
> Good morning,
>
> I don't recal reviewing the first revision of this set. Can you provide a link
> to it so that I can read the comments that were provided?
>
Here it is:
https://lore.kernel.org/linux-remoteproc/20260422202558.2362971-1-tanmay.shah@amd.com/
The device-tree bindings needed rework in v1, so I sent v2, before we
ever reviewed the driver part.
> On Fri, May 01, 2026 at 07:37:07AM -0700, Tanmay Shah wrote:
>> remoteproc framework has capability to start (or attach to) the remote
>
> The remoteproc framework...
>
Ack.
>> processor automatically if auto boot flag is set by the driver during
>> probe. If remote core is not started before the Linux boot, and linux is
>> expected to start the remote core then it uses "firmware-name" property
>> to load default firmware during auto boot.
>>
>> Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
>> ---
>> drivers/remoteproc/xlnx_r5_remoteproc.c | 48 +++++++++++++++++--------
>> 1 file changed, 34 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
>> index 45a62cb98072..652030f9cea2 100644
>> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
>> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
>> @@ -899,17 +899,18 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = {
>> };
>>
>> /**
>> - * zynqmp_r5_add_rproc_core() - Add core data to framework.
>> - * Allocate and add struct rproc object for each r5f core
>> + * zynqmp_r5_alloc_rproc_core() - alloc rproc core data structure
>> + * Allocate struct rproc object for each r5f core
>> * This is called for each individual r5f core
>> *
>> * @cdev: Device node of each r5 core
>> *
>> * Return: zynqmp_r5_core object for success else error code pointer
>> */
>> -static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>> +static struct zynqmp_r5_core *zynqmp_r5_alloc_rproc_core(struct device *cdev)
>
> Why is there a need to change the function's name?
>
Before, the function was actually adding the rproc core by calling
rproc_add() function, but now it only allocates the memory by calling
rproc_alloc(). For auto boot to work it's important to add rproc core
after all the other hw is initialized (such as mbox, tcm, sram,
power-domains etc). More details below [1].
>> {
>> struct zynqmp_r5_core *r5_core;
>> + const char *fw_name = NULL;
>> struct rproc *r5_rproc;
>> int ret;
>>
>> @@ -918,10 +919,15 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>> if (ret)
>> return ERR_PTR(ret);
>>
>> + ret = rproc_of_parse_firmware(cdev, 0, &fw_name);
>> + if (ret < 0 && ret != -EINVAL)
>> + return ERR_PTR(dev_err_probe(cdev, ret,
>> + "failed to parse firmware-name\n"));
>> +
>> /* Allocate remoteproc instance */
>> r5_rproc = rproc_alloc(cdev, dev_name(cdev),
>> &zynqmp_r5_rproc_ops,
>> - NULL, sizeof(struct zynqmp_r5_core));
>> + fw_name, sizeof(struct zynqmp_r5_core));
>> if (!r5_rproc) {
>> dev_err(cdev, "failed to allocate memory for rproc instance\n");
>> return ERR_PTR(-ENOMEM);
>> @@ -932,6 +938,11 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>> r5_rproc->recovery_disabled = true;
>> r5_rproc->has_iommu = false;
>> r5_rproc->auto_boot = false;
>> +
>> + /* attempt to boot automatically if the firmware-name is provided */
>> + if (fw_name)
>> + r5_rproc->auto_boot = true;
>> +
>
> What happens when a firmware name needs to be provided in the DT but you don't
> want to automatically boot the remote processor?
>
I think that use case is not needed. If the user/system-designer doesn't
want auto-boot, then having firmware-name in the device-tree serves no
purpose. User can always load the firmware via sysfs once kernel boots.
>> r5_core = r5_rproc->priv;
>> r5_core->dev = cdev;
>> r5_core->np = dev_of_node(cdev);
>> @@ -941,13 +952,6 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>> goto free_rproc;
>> }
>>
>> - /* Add R5 remoteproc core */
>> - ret = rproc_add(r5_rproc);
>> - if (ret) {
>> - dev_err(cdev, "failed to add r5 remoteproc\n");
>> - goto free_rproc;
>> - }
>> -
>
> I'm not sure why there is a need to move this to zynqmp_r5_cluster_init()? Is
> it simply to make the error path easier to handle? If so, please do that in a
> separate patch.
>
[1] This was moved to make auto-boot work. The remote core can auto-boot
only after other hardware is initialized. The zynqmp_r5_core_init()
initializes sram, TCM and power-domains of the core. Also, mailbox is
requested before zynqmp_r5_core_init() as well. We can't auto-boot core
directly without all this. So, I had to move rproc_add() at the end of
the cluster init, and rename above function from
zynqmp_r5_add_rproc_core to zynqmp_r5_alloc_rproc_core.
If you prefer, I will add above explanation in the commit text, or as
comment right before rproc_add().
>> r5_core->rproc = r5_rproc;
>> return r5_core;
>>
>> @@ -1280,6 +1284,7 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
>> if (zynqmp_r5_get_rsc_table_va(r5_core))
>> dev_dbg(r5_core->dev, "rsc tbl not found\n");
>> r5_core->rproc->state = RPROC_DETACHED;
>> + r5_core->rproc->auto_boot = true;
>
> I thought this was done in zynqmp_r5_add_rproc_core() - what am I missing?
>
That function is now zynqmp_r5_alloc_core() as mentioned above. Also,
until now, auto_boot was set to 'false' only to show that it is
disabled. It is actually used and enabled now.
> Thanks,
> Mathieu
>
>> }
>> }
>>
>> @@ -1304,7 +1309,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>> enum rpu_oper_mode fw_reg_val;
>> struct device **child_devs;
>> enum rpu_tcm_comb tcm_mode;
>> - int core_count, ret, i;
>> + int core_count, ret, i, j;
>> struct mbox_info *ipi;
>>
>> ret = of_property_read_u32(dev_node, "xlnx,cluster-mode", &cluster_mode);
>> @@ -1390,7 +1395,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>> child_devs[i] = &child_pdev->dev;
>>
>> /* create and add remoteproc instance of type struct rproc */
>> - r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev);
>> + r5_cores[i] = zynqmp_r5_alloc_rproc_core(&child_pdev->dev);
>> if (IS_ERR(r5_cores[i])) {
>> ret = PTR_ERR(r5_cores[i]);
>> r5_cores[i] = NULL;
>> @@ -1435,16 +1440,31 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>> goto release_r5_cores;
>> }
>>
>> + for (j = 0; j < cluster->core_count; j++) {
>> + /* Add R5 remoteproc core */
>> + ret = rproc_add(r5_cores[j]->rproc);
>> + if (ret) {
>> + dev_err_probe(r5_cores[j]->dev, ret,
>> + "failed to add remoteproc\n");
>> + goto delete_r5_cores;
>> + }
>> + }
>> +
>> kfree(child_devs);
>> return 0;
>>
>> +delete_r5_cores:
>> + i = core_count - 1;
>> + /* delete previous added rproc */
>> + while (--j >= 0)
>> + rproc_del(r5_cores[j]->rproc);
>> +
>> release_r5_cores:
>> while (i >= 0) {
>> put_device(child_devs[i]);
>> if (r5_cores[i]) {
>> zynqmp_r5_free_mbox(r5_cores[i]->ipi);
>> of_reserved_mem_device_release(r5_cores[i]->dev);
>> - rproc_del(r5_cores[i]->rproc);
>> rproc_free(r5_cores[i]->rproc);
>> }
>> i--;
>> --
>> 2.34.1
>>
^ permalink raw reply
* Re: [PATCH v2] net: stmmac: mmc: Remove duplicate mmc_rx crc
From: Andrew Lunn @ 2026-05-21 18:44 UTC (permalink / raw)
To: dev.taqnialabs
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, netdev,
linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20260521-xgmac-mmc_rx_crc-cleanup-v2-1-7d9de09f5898@gmail.com>
On Thu, May 21, 2026 at 04:32:46PM +0000, Abid Ali via B4 Relay wrote:
> From: Abid Ali <dev.taqnialabs@gmail.com>
>
> MMC_XGMAC_RX_CRC_ERR is clear-on-read, and just a single read would
> update the mmc_rx_crc_error counter.
>
> [1] commit b6cdf09 ("net: stmmac: xgmac: Implement MMC counters").
> The duplicate read appears to have been unintentionally introduced in
> the intial MMC counter implementation. The databook does not mention
> MMC_XGMAC_RX_CRC_ERR needing the additional read.
Thanks for the updated commit message.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH v2 2/2] remoteproc: xlnx: enable auto boot feature
From: Shah, Tanmay @ 2026-05-21 18:48 UTC (permalink / raw)
To: Mathieu Poirier, Tanmay Shah
Cc: andersson, robh, krzk+dt, conor+dt, michal.simek, ben.levinsky,
linux-remoteproc, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <cbd418a3-1585-4592-8e86-b0750e19ec0f@amd.com>
On 5/21/2026 1:38 PM, Shah, Tanmay wrote:
> Hello,
>
> Thank you for the reviews, please find my comments below:
>
> On 5/21/2026 12:48 PM, Mathieu Poirier wrote:
>> Good morning,
>>
>> I don't recal reviewing the first revision of this set. Can you provide a link
>> to it so that I can read the comments that were provided?
>>
>
> Here it is:
> https://lore.kernel.org/linux-remoteproc/20260422202558.2362971-1-tanmay.shah@amd.com/
>
> The device-tree bindings needed rework in v1, so I sent v2, before we
> ever reviewed the driver part.
>
>
>> On Fri, May 01, 2026 at 07:37:07AM -0700, Tanmay Shah wrote:
>>> remoteproc framework has capability to start (or attach to) the remote
>>
>> The remoteproc framework...
>>
>
> Ack.
>
>>> processor automatically if auto boot flag is set by the driver during
>>> probe. If remote core is not started before the Linux boot, and linux is
>>> expected to start the remote core then it uses "firmware-name" property
>>> to load default firmware during auto boot.
>>>
>>> Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
>>> ---
>>> drivers/remoteproc/xlnx_r5_remoteproc.c | 48 +++++++++++++++++--------
>>> 1 file changed, 34 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
>>> index 45a62cb98072..652030f9cea2 100644
>>> --- a/drivers/remoteproc/xlnx_r5_remoteproc.c
>>> +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
>>> @@ -899,17 +899,18 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = {
>>> };
>>>
>>> /**
>>> - * zynqmp_r5_add_rproc_core() - Add core data to framework.
>>> - * Allocate and add struct rproc object for each r5f core
>>> + * zynqmp_r5_alloc_rproc_core() - alloc rproc core data structure
>>> + * Allocate struct rproc object for each r5f core
>>> * This is called for each individual r5f core
>>> *
>>> * @cdev: Device node of each r5 core
>>> *
>>> * Return: zynqmp_r5_core object for success else error code pointer
>>> */
>>> -static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>>> +static struct zynqmp_r5_core *zynqmp_r5_alloc_rproc_core(struct device *cdev)
>>
>> Why is there a need to change the function's name?
>>
>
> Before, the function was actually adding the rproc core by calling
> rproc_add() function, but now it only allocates the memory by calling
> rproc_alloc(). For auto boot to work it's important to add rproc core
> after all the other hw is initialized (such as mbox, tcm, sram,
> power-domains etc). More details below [1].
>
>>> {
>>> struct zynqmp_r5_core *r5_core;
>>> + const char *fw_name = NULL;
>>> struct rproc *r5_rproc;
>>> int ret;
>>>
>>> @@ -918,10 +919,15 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>>> if (ret)
>>> return ERR_PTR(ret);
>>>
>>> + ret = rproc_of_parse_firmware(cdev, 0, &fw_name);
>>> + if (ret < 0 && ret != -EINVAL)
>>> + return ERR_PTR(dev_err_probe(cdev, ret,
>>> + "failed to parse firmware-name\n"));
>>> +
>>> /* Allocate remoteproc instance */
>>> r5_rproc = rproc_alloc(cdev, dev_name(cdev),
>>> &zynqmp_r5_rproc_ops,
>>> - NULL, sizeof(struct zynqmp_r5_core));
>>> + fw_name, sizeof(struct zynqmp_r5_core));
>>> if (!r5_rproc) {
>>> dev_err(cdev, "failed to allocate memory for rproc instance\n");
>>> return ERR_PTR(-ENOMEM);
>>> @@ -932,6 +938,11 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>>> r5_rproc->recovery_disabled = true;
>>> r5_rproc->has_iommu = false;
>>> r5_rproc->auto_boot = false;
>>> +
>>> + /* attempt to boot automatically if the firmware-name is provided */
>>> + if (fw_name)
>>> + r5_rproc->auto_boot = true;
>>> +
>>
>> What happens when a firmware name needs to be provided in the DT but you don't
>> want to automatically boot the remote processor?
>>
>
> I think that use case is not needed. If the user/system-designer doesn't
> want auto-boot, then having firmware-name in the device-tree serves no
> purpose. User can always load the firmware via sysfs once kernel boots.
>
>>> r5_core = r5_rproc->priv;
>>> r5_core->dev = cdev;
>>> r5_core->np = dev_of_node(cdev);
>>> @@ -941,13 +952,6 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
>>> goto free_rproc;
>>> }
>>>
>>> - /* Add R5 remoteproc core */
>>> - ret = rproc_add(r5_rproc);
>>> - if (ret) {
>>> - dev_err(cdev, "failed to add r5 remoteproc\n");
>>> - goto free_rproc;
>>> - }
>>> -
>>
>> I'm not sure why there is a need to move this to zynqmp_r5_cluster_init()? Is
>> it simply to make the error path easier to handle? If so, please do that in a
>> separate patch.
>>
>
> [1] This was moved to make auto-boot work. The remote core can auto-boot
> only after other hardware is initialized. The zynqmp_r5_core_init()
> initializes sram, TCM and power-domains of the core. Also, mailbox is
> requested before zynqmp_r5_core_init() as well. We can't auto-boot core
> directly without all this. So, I had to move rproc_add() at the end of
> the cluster init, and rename above function from
> zynqmp_r5_add_rproc_core to zynqmp_r5_alloc_rproc_core.
>
> If you prefer, I will add above explanation in the commit text, or as
> comment right before rproc_add().
>
>
>
>>> r5_core->rproc = r5_rproc;
>>> return r5_core;
>>>
>>> @@ -1280,6 +1284,7 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
>>> if (zynqmp_r5_get_rsc_table_va(r5_core))
>>> dev_dbg(r5_core->dev, "rsc tbl not found\n");
>>> r5_core->rproc->state = RPROC_DETACHED;
>>> + r5_core->rproc->auto_boot = true;
>>
>> I thought this was done in zynqmp_r5_add_rproc_core() - what am I missing?
>>
>
> That function is now zynqmp_r5_alloc_core() as mentioned above. Also,
> until now, auto_boot was set to 'false' only to show that it is
> disabled. It is actually used and enabled now.
>
"I thought this was done in zynqmp_r5_add_rproc_core() - what am I missing?"
I probably misunderstood this comment. Here is the correct explanation:
The auto_boot setting in the zynqmp_r5_alloc_core() is done if the
'firmware-name' property is present in the device-tree.
Here it is done, if the remote core is already running. This is to
support attach-detach use case.
So, auto_boot is possible in two cases: 1) If firmware-name property is
available (Linux boots the remote), 2) If firmware is already loaded and
remote was started by the boot loader. (Linux attaches to the running
remote).
This is the second use case.
Thanks,
Tanmay
>> Thanks,
>> Mathieu
>>
>>> }
>>> }
>>>
>>> @@ -1304,7 +1309,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>>> enum rpu_oper_mode fw_reg_val;
>>> struct device **child_devs;
>>> enum rpu_tcm_comb tcm_mode;
>>> - int core_count, ret, i;
>>> + int core_count, ret, i, j;
>>> struct mbox_info *ipi;
>>>
>>> ret = of_property_read_u32(dev_node, "xlnx,cluster-mode", &cluster_mode);
>>> @@ -1390,7 +1395,7 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>>> child_devs[i] = &child_pdev->dev;
>>>
>>> /* create and add remoteproc instance of type struct rproc */
>>> - r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev);
>>> + r5_cores[i] = zynqmp_r5_alloc_rproc_core(&child_pdev->dev);
>>> if (IS_ERR(r5_cores[i])) {
>>> ret = PTR_ERR(r5_cores[i]);
>>> r5_cores[i] = NULL;
>>> @@ -1435,16 +1440,31 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
>>> goto release_r5_cores;
>>> }
>>>
>>> + for (j = 0; j < cluster->core_count; j++) {
>>> + /* Add R5 remoteproc core */
>>> + ret = rproc_add(r5_cores[j]->rproc);
>>> + if (ret) {
>>> + dev_err_probe(r5_cores[j]->dev, ret,
>>> + "failed to add remoteproc\n");
>>> + goto delete_r5_cores;
>>> + }
>>> + }
>>> +
>>> kfree(child_devs);
>>> return 0;
>>>
>>> +delete_r5_cores:
>>> + i = core_count - 1;
>>> + /* delete previous added rproc */
>>> + while (--j >= 0)
>>> + rproc_del(r5_cores[j]->rproc);
>>> +
>>> release_r5_cores:
>>> while (i >= 0) {
>>> put_device(child_devs[i]);
>>> if (r5_cores[i]) {
>>> zynqmp_r5_free_mbox(r5_cores[i]->ipi);
>>> of_reserved_mem_device_release(r5_cores[i]->dev);
>>> - rproc_del(r5_cores[i]->rproc);
>>> rproc_free(r5_cores[i]->rproc);
>>> }
>>> i--;
>>> --
>>> 2.34.1
>>>
>
^ permalink raw reply
* Re: [PATCH] pwm: imx27: Fix variable truncation in .apply()
From: Frank Li @ 2026-05-21 18:56 UTC (permalink / raw)
To: Ronaldo Nunez
Cc: linux-pwm, Uwe Kleine-König, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, imx, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260521000054.4790-1-rnunez@baylibre.com>
On Wed, May 20, 2026 at 09:00:54PM -0300, Ronaldo Nunez wrote:
> This patch fixes a variable truncation when calculating period in
Remove "This Patch" just
Fix a variable 'tmp' truncation when calculating period in
> microseconds as part of the solution for the ERR051198 in .apply()
> callback.
>
> The problem was identified when reducing the duty cycle through sysfs,
> with enable set to 1. The condition to fix errata ERR051198 for period
> smaller than 2us is always being met, due to a truncation on tmp,
> variable from .apply() callback, caused by the multiplication of
> NSEC_PER_SEC, PWMPR (period register) and the prescaler which can easily
> overflow u32.
It'd better provide actual example value for PWMPR and prescaler when
overflow happen.
> Declaring tmp as u64 makes it large enough to accommodate
> larger multiplication results.
>
> Testing:
> - Hardware: Udoo Neo Extended with iMX6SoloX SoC
> - Tools: Verified with a logic analyzer
needn't this part.
Frank
>
> Signed-off-by: Ronaldo Nunez <rnunez@baylibre.com>
> ---
> drivers/pwm/pwm-imx27.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
> index 3d34cdc4a3a5..c8b801fcb525 100644
> --- a/drivers/pwm/pwm-imx27.c
> +++ b/drivers/pwm/pwm-imx27.c
> @@ -200,7 +200,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
> static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> const struct pwm_state *state)
> {
> - unsigned long period_cycles, duty_cycles, prescale, period_us, tmp;
> + unsigned long period_cycles, duty_cycles, prescale, period_us;
> struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
> unsigned long long c;
> unsigned long long clkrate;
> @@ -208,6 +208,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> int val;
> int ret;
> u32 cr;
> + u64 tmp;
>
> clkrate = clk_get_rate(imx->clks[PWM_IMX27_PER].clk);
> c = clkrate * state->period;
> @@ -249,6 +250,11 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> val = readl(imx->mmio_base + MX3_PWMPR);
> val = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
> cr = readl(imx->mmio_base + MX3_PWMCR);
> +
> + /*
> + * tmp stores period in nanoseconds. Result fits in u64 since
> + * val <= 0xfffe and prescaler in [1, 0x1000].
> + */
> tmp = NSEC_PER_SEC * (u64)(val + 2) * MX3_PWMCR_PRESCALER_GET(cr);
> tmp = DIV_ROUND_UP_ULL(tmp, clkrate);
> period_us = DIV_ROUND_UP_ULL(tmp, 1000);
> --
> 2.53.0
>
^ permalink raw reply
* [PATCH] ARM: zte: clean up zx297520v3 doc. warnings
From: Randy Dunlap @ 2026-05-21 19:14 UTC (permalink / raw)
To: linux-kernel
Cc: Randy Dunlap, Stefan Dösinger, Linus Walleij,
Krzysztof Kozlowski, linux-arm-kernel, Jonathan Corbet,
Shuah Khan, linux-doc
Fix multiple documentation build warnings.
Improve punctuation and formatting of the rendered output.
Documentation/arch/arm/zte/zx297520v3.rst:66: WARNING: Title underline too short.
3. Building for built-in U-Boot
--------------------------- [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:90: WARNING: Enumerated list ends without a blank line; unexpected unindent. [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:116: WARNING: Inline literal start-string without end-string. [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:137: ERROR: Unexpected indentation. [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:138: WARNING: Block quote ends without a blank line; unexpected unindent. [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:164: WARNING: Inline literal start-string without end-string. [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:164: WARNING: Inline interpreted text or phrase reference start-string without end-string. [docutils]
Documentation/arch/arm/zte/zx297520v3.rst:7: WARNING: Document or section may not begin with a transition. [docutils]
Fixes: 220ae5d36dba ("ARM: zte: Add zx297520v3 platform support")
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
---
Cc: Stefan Dösinger <stefandoesinger@gmail.com>
Cc: Linus Walleij <linusw@kernel.org>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Shuah Khan <skhan@linuxfoundation.org>
Cc: linux-doc@vger.kernel.org
Documentation/arch/arm/zte/zx297520v3.rst | 119 +++++++++-----------
1 file changed, 59 insertions(+), 60 deletions(-)
--- linux-next.orig/Documentation/arch/arm/zte/zx297520v3.rst
+++ linux-next/Documentation/arch/arm/zte/zx297520v3.rst
@@ -4,15 +4,13 @@
Booting Linux on ZTE zx297520v3 SoCs
====================================
-...............................................................................
-
Author: Stefan Dösinger
Date : 27 Jan 2026
1. Hardware description
---------------------------
-Zx297520v3 SoCs use a 64 bit capable Cortex-A53 CPU and GICv3, although they
+Zx297520v3 SoCs use a 64-bit capable Cortex-A53 CPU and GICv3, although they
run in arm32 mode only. The CPU has support EL3, but no hypervisor (EL2) and
it seems to lack VFP and NEON.
@@ -27,7 +25,7 @@ Some devices, especially the stationary
Ethernet switch.
Usually the devices have LEDs for status indication, although some have SPI or
-I2C connected displays
+I2C connected displays.
Some have an SD card slot. If it exists, it is a better choice for the root
file system because it easily outperforms the built-in NAND.
@@ -39,7 +37,7 @@ IRQs on either ends.
There is also a Cortex M0 CPU, which is responsible for early HW initialization
and starting the Cortex A53 CPU. It does not have any essential purpose once
-U-Boot is started. A SRAM-Based handover protocol exists to run custom code on
+U-Boot is started. An SRAM-based handover protocol exists to run custom code on
this CPU.
2. Booting via USB
@@ -63,13 +61,13 @@ Contains an U-Boot version that can be u
CPU and interrupt controller to comply with Linux's booting requirements.
3. Building for built-in U-Boot
----------------------------
+-------------------------------
The devices come with an ancient U-Boot that loads legacy uImages from NAND and
boots them without a chance for the user to interrupt. The images are stored in
files ap_cpuap.bin and ap_recovery.bin on a jffs2 partition named imagefs,
usually mtd4. A file named "fotaflag" switches between the two modes.
-In addition to the uImage header, those files have a 384 byte signature header,
+In addition to the uImage header, those files have a 384-byte signature header,
which is used for authenticating the images on some devices. Most devices have
this authentication disabled and it is enough to pad the uImage files with 384
zero bytes.
@@ -88,7 +86,7 @@ So to build an image that boots from NAN
6) dd if=/dev/zero bs=1 count=384 of=ap_recovery.bin
7) cat uimg >> ap_recovery.bin
8) Place this file onto imagefs on the device. Delete ap_cpuap.bin if the
-free space is not enough.
+ free space is not enough.
9) Create the file fotaflag: echo -n FOTA-RECOVERY > fotaflag
For development, booting ap_recovery.bin is recommended because the normal boot
@@ -113,55 +111,56 @@ the binary blobs.
The assembly code below is given as an example of how to achieve this:
-```
-#include <linux/irqchip/arm-gic-v3.h>
-#include <asm/assembler.h>
-#include <asm/cp15.h>
-
-@ Detect sane bootloaders and skip the hack
-ldr r3, =0xf2000000
-ldr r3, [r3]
-ldr r4, =(GICD_CTLR_ARE_NS | GICD_CTLR_DS)
-cmp r3, r4
-beq skip_zx_hack
-@ This allows EL1 to handle ints hat are normally handled by EL2/3.
-ldr r3, =0xf2000000
-str r4, [r3]
-
-cps #MON_MODE
-
-@ Work in non-secure physical address space: SCR_EL3.NS = 1. At least the UART
-@ seems to respond only to non-secure addresses. I have taken insipiration from
-@ Raspberry pi's armstub7.S here.
-mov r3, #0x131 @ non-secure, Make F, A bits in CPSR writeable
- @ Allow hypervisor call.
-mcr p15, 0, r3, c1, c1, 0
-
-@ AP_PPI_MODE_REG: Configure timer PPIs (10, 11, 13, 14) to active-low.
-ldr r3, =0xF22020a8
-ldr r4, =0x50
-str r4, [r3]
-ldr r3, =0xF22020ac
-ldr r4, =0x14
-str r4, [r3]
-
-@ Enable EL2 access to ICC_SRE (bit 3, ICC_SRE_EL3.Enable). Enable system reg
-@ access to GICv3 registers (bit 0, ICC_SRE_EL3.SRE) for EL1 and EL3.
-mrc p15, 6, r3, c12, c12, 5 @ ICC_SRE_EL3
-orr r3, #0x9 @ FIXME: No defines for SRE_EL3 values?
-mcr p15, 6, r3, c12, c12, 5
-mrc p15, 0, r3, c12, c12, 5 @ ICC_SRE_EL1
-orr r3, #(ICC_SRE_EL1_SRE)
-mcr p15, 0, r3, c12, c12, 5
-
-@ Like ICC_SRE_EL3, enable EL1 access to ICC_SRE and system register access
-@ for EL2.
-mrc p15, 4, r3, c12, c9, 5 @ ICC_SRE_EL2 aka ICC_HSRE
-orr r3, r3, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
-mcr p15, 4, r3, c12, c9, 5
-isb
-
-@ Back to SVC mode
-cps #SVC_MODE
-skip_zx_hack:
-```
+::
+
+ #include <linux/irqchip/arm-gic-v3.h>
+ #include <asm/assembler.h>
+ #include <asm/cp15.h>
+
+ @ Detect sane bootloaders and skip the hack
+ ldr r3, =0xf2000000
+ ldr r3, [r3]
+ ldr r4, =(GICD_CTLR_ARE_NS | GICD_CTLR_DS)
+ cmp r3, r4
+ beq skip_zx_hack
+ @ This allows EL1 to handle ints hat are normally handled by EL2/3.
+ ldr r3, =0xf2000000
+ str r4, [r3]
+
+ cps #MON_MODE
+
+ @ Work in non-secure physical address space: SCR_EL3.NS = 1. At least the UART
+ @ seems to respond only to non-secure addresses. I have taken insipiration from
+ @ Raspberry pi's armstub7.S here.
+ mov r3, #0x131 @ non-secure, Make F, A bits in CPSR writeable
+ @ Allow hypervisor call.
+ mcr p15, 0, r3, c1, c1, 0
+
+ @ AP_PPI_MODE_REG: Configure timer PPIs (10, 11, 13, 14) to active-low.
+ ldr r3, =0xF22020a8
+ ldr r4, =0x50
+ str r4, [r3]
+ ldr r3, =0xF22020ac
+ ldr r4, =0x14
+ str r4, [r3]
+
+ @ Enable EL2 access to ICC_SRE (bit 3, ICC_SRE_EL3.Enable). Enable system reg
+ @ access to GICv3 registers (bit 0, ICC_SRE_EL3.SRE) for EL1 and EL3.
+ mrc p15, 6, r3, c12, c12, 5 @ ICC_SRE_EL3
+ orr r3, #0x9 @ FIXME: No defines for SRE_EL3 values?
+ mcr p15, 6, r3, c12, c12, 5
+ mrc p15, 0, r3, c12, c12, 5 @ ICC_SRE_EL1
+ orr r3, #(ICC_SRE_EL1_SRE)
+ mcr p15, 0, r3, c12, c12, 5
+
+ @ Like ICC_SRE_EL3, enable EL1 access to ICC_SRE and system register access
+ @ for EL2.
+ mrc p15, 4, r3, c12, c9, 5 @ ICC_SRE_EL2 aka ICC_HSRE
+ orr r3, r3, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
+ mcr p15, 4, r3, c12, c9, 5
+ isb
+
+ @ Back to SVC mode
+ cps #SVC_MODE
+ skip_zx_hack:
+
^ permalink raw reply
* [PATCH v2 1/6] ARM: dts: imx: add (power|vdd)-supply for related node
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20260521-imx25_dts_simple_warning_2-v2-0-c6557df516a9@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Add required power-supply and vdd-supply properties to fix below CHECK_DTB
warnings:
arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dtb: panel (edt,etm0700g0dh6): 'power-supply' is a required property
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v2
- change regulator name to 5v (sashika AI)
---
arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts | 9 +++++++++
arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi | 1 +
arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts | 7 +++++++
arch/arm/boot/dts/nxp/imx/imx6q-novena.dts | 1 +
4 files changed, 18 insertions(+)
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
index 6210673f93bea..2acbc86cabb31 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
@@ -84,6 +84,7 @@ panel {
pinctrl-0 = <&pinctrl_display_gpio>;
pinctrl-names = "default";
enable-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
+ power-supply = <®_3p2v>;
port {
panel_in: endpoint {
@@ -98,6 +99,13 @@ beeper {
gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
};
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
reg_usbh1_vbus: regulator-usbh1-vbus {
compatible = "regulator-fixed";
regulator-name = "vbus";
@@ -259,6 +267,7 @@ eeprom@50 {
dac@60 {
compatible = "microchip,mcp4725";
reg = <0x60>;
+ vdd-supply = <®_3v3>;
};
};
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi
index e395004e80e6d..34cb0c344ff6e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi
@@ -10,6 +10,7 @@
/ {
panel: panel-rgb {
compatible = "powertip,ph800480t013-idf02";
+ power-supply = <®_5v>;
port {
panel_rgb_in: endpoint {
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts
index 1a00d290092ad..ebec884958776 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts
@@ -29,6 +29,13 @@ memory@70000000 {
reg = <0x70000000 0x20000000>;
};
+ reg_5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
reg_usb1_vbus: regulator-usb-vbus {
compatible = "regulator-fixed";
regulator-name = "usb_vbus";
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts b/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts
index 24fc3ff1c70c2..cd9a050fa906e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-novena.dts
@@ -109,6 +109,7 @@ led-heartbeat {
panel: panel {
compatible = "innolux,n133hse-ea1";
backlight = <&backlight>;
+ power-supply = <®_lvds_lcd>;
};
reg_2p5v: regulator-2p5v {
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/6] ARM: dts: cleanup some CHECK_DTBS warning for imx5/6 (round 2)
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
Cleanup CHECK_DTBS warning for imx_v6_v7_defconfig. (below 500 line warning
left) after apply pending binding doc patch.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v2:
- fix sashiko AI's feedback, detail see each patch's change log
- Link to v1: https://lore.kernel.org/r/20260515-imx25_dts_simple_warning_2-v1-0-b06bff192a05@nxp.com
---
Frank Li (6):
ARM: dts: imx: add (power|vdd)-supply for related node
ARM: dts: imx: remove redundant bus-width for video-mux
ARM: dts: imx: Add bus-type for ov5642/ov5640
ARM: dts: imx6qdl-tx6: remove undocumented karo,imx6qdl-tx6-sgtl5000 and keep only simple-audio-card
ARM: dts: imx: replace undocumented compatible string edt,edt-ft5x06 with edt,edt-ft5206
ARM: dts: imx6-display5: replace marvell,88E1510 with ethernet-phy-ieee802.3-c22
arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts | 11 ++++++++++-
arch/arm/boot/dts/nxp/imx/imx53-sk-imx53-atm0700d4.dtsi | 1 +
arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts | 7 +++++++
arch/arm/boot/dts/nxp/imx/imx53-smd.dts | 2 ++
arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts | 4 ----
arch/arm/boot/dts/nxp/imx/imx6q-novena.dts | 1 +
arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi | 5 ++---
arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi | 1 +
arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts | 2 +-
30 files changed, 37 insertions(+), 39 deletions(-)
---
base-commit: d26bfe9856a36453f591b9620dac996ff9f02443
change-id: 20260511-imx25_dts_simple_warning_2-10d3c75b8889
Best regards,
--
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply
* [PATCH v2 2/6] ARM: dts: imx: remove redundant bus-width for video-mux
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20260521-imx25_dts_simple_warning_2-v2-0-c6557df516a9@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Remove redundant bus-width property according to video-mux.yaml to fix
below CHECK_DTBS warnings:
arch/arm/boot/dts/nxp/imx/imx6dl-gw51xx.dtb: ipu1_csi0_mux (video-mux): port@4:endpoint: Unevaluated properties are not allowed ('bus-width' was unexpected)
from schema $id: http://devicetree.org/schemas/media/video-mux.yaml
The bus-width already set at remote endpoint (camera).
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts | 2 --
arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts | 4 ----
arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi | 2 --
arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi | 2 --
10 files changed, 22 deletions(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts
index 9ea23dd54f3ce..62b05fe70cd97 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-gw52xx.dts
@@ -32,12 +32,10 @@ adv7180_to_ipu1_csi1_mux: endpoint {
};
&ipu1_csi1_from_ipu1_csi1_mux {
- bus-width = <8>;
};
&ipu1_csi1_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu1_csi1_mux>;
- bus-width = <8>;
};
&ipu1_csi1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts
index 182e8194c2490..c1787510d3941 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-gw53xx.dts
@@ -32,12 +32,10 @@ adv7180_to_ipu1_csi1_mux: endpoint {
};
&ipu1_csi1_from_ipu1_csi1_mux {
- bus-width = <8>;
};
&ipu1_csi1_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu1_csi1_mux>;
- bus-width = <8>;
};
&ipu1_csi1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts
index a106c4e3e3299..934b0325e6f5a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6dl-gw54xx.dts
@@ -32,12 +32,10 @@ adv7180_to_ipu1_csi1_mux: endpoint {
};
&ipu1_csi1_from_ipu1_csi1_mux {
- bus-width = <8>;
};
&ipu1_csi1_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu1_csi1_mux>;
- bus-width = <8>;
};
&ipu1_csi1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts
index 6e1c493c9c8c4..31996ddde117a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-gw52xx.dts
@@ -32,12 +32,10 @@ adv7180_to_ipu2_csi1_mux: endpoint {
};
&ipu2_csi1_from_ipu2_csi1_mux {
- bus-width = <8>;
};
&ipu2_csi1_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu2_csi1_mux>;
- bus-width = <8>;
};
&ipu2_csi1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts
index f13df8e9c8c4b..f224273fa863e 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-gw53xx.dts
@@ -32,12 +32,10 @@ adv7180_to_ipu2_csi1_mux: endpoint {
};
&ipu2_csi1_from_ipu2_csi1_mux {
- bus-width = <8>;
};
&ipu2_csi1_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu2_csi1_mux>;
- bus-width = <8>;
};
&ipu2_csi1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts b/arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts
index d5d46908cf6ed..804ee044be52d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-gw54xx.dts
@@ -90,12 +90,10 @@ tda1997x_to_ipu1_csi0_mux: endpoint {
};
&ipu1_csi0_from_ipu1_csi0_mux {
- bus-width = <16>;
};
&ipu1_csi0_mux_from_parallel_sensor {
remote-endpoint = <&tda1997x_to_ipu1_csi0_mux>;
- bus-width = <16>;
};
&ipu1_csi0 {
@@ -104,12 +102,10 @@ &ipu1_csi0 {
};
&ipu2_csi1_from_ipu2_csi1_mux {
- bus-width = <8>;
};
&ipu2_csi1_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu2_csi1_mux>;
- bus-width = <8>;
};
&ipu2_csi1 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi
index beff5a0f58ab4..fb18b87adb441 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw51xx.dtsi
@@ -384,12 +384,10 @@ adv7180_to_ipu1_csi0_mux: endpoint {
};
&ipu1_csi0_from_ipu1_csi0_mux {
- bus-width = <8>;
};
&ipu1_csi0_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu1_csi0_mux>;
- bus-width = <8>;
};
&ipu1_csi0 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi
index 6136a95b92599..55647c1dacfa5 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw551x.dtsi
@@ -440,12 +440,10 @@ tda1997x_to_ipu1_csi0_mux: endpoint {
};
&ipu1_csi0_from_ipu1_csi0_mux {
- bus-width = <16>;
};
&ipu1_csi0_mux_from_parallel_sensor {
remote-endpoint = <&tda1997x_to_ipu1_csi0_mux>;
- bus-width = <16>;
};
&ipu1_csi0 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi
index 552114a69f5b9..bdbcad5e35d82 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw553x.dtsi
@@ -397,12 +397,10 @@ adv7180_to_ipu1_csi0_mux: endpoint {
};
&ipu1_csi0_from_ipu1_csi0_mux {
- bus-width = <8>;
};
&ipu1_csi0_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu1_csi0_mux>;
- bus-width = <8>;
};
&ipu1_csi0 {
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
index b9dde0af3b995..40d8887cb8bc7 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi
@@ -245,12 +245,10 @@ accelerometer@1c {
};
&ipu1_csi0_from_ipu1_csi0_mux {
- bus-width = <8>;
};
&ipu1_csi0_mux_from_parallel_sensor {
remote-endpoint = <&adv7180_to_ipu1_csi0_mux>;
- bus-width = <8>;
};
&ipu1_csi0 {
--
2.43.0
^ permalink raw reply related
* [PATCH v2 4/6] ARM: dts: imx6qdl-tx6: remove undocumented karo,imx6qdl-tx6-sgtl5000 and keep only simple-audio-card
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20260521-imx25_dts_simple_warning_2-v2-0-c6557df516a9@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Remove the undocumented and unused compatible karo,imx6qdl-tx6-sgtl5000 and
retain only the generic simple-audio-card sound configuration.
The karo,imx6qdl-tx6-sgtl5000 compatible is not documented and is not
referenced by any in-kernel driver. The audio setup is already fully
described using simple-audio-card, which is the standard and supported
binding for this hardware configuration.
No known users (such as uboot) rely on karo,imx6qdl-tx6-sgtl5000.
Fix below CHECK_DTBS warnings:
arch/arm/boot/dts/nxp/imx/imx6dl-tx6dl-comtft.dtb: /sound: failed to match any schema with compatible: ['karo,imx6qdl-tx6-sgtl5000', 'simple-audio-card']
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
index 57297d6521cf0..ec1528ff3ea01 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
@@ -148,8 +148,7 @@ reg_usbotg_vbus: regulator-usbotg-vbus {
};
sound {
- compatible = "karo,imx6qdl-tx6-sgtl5000",
- "simple-audio-card";
+ compatible = "simple-audio-card";
simple-audio-card,name = "imx6qdl-tx6-sgtl5000-audio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 3/6] ARM: dts: imx: Add bus-type for ov5642/ov5640
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20260521-imx25_dts_simple_warning_2-v2-0-c6557df516a9@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Add bus-type (MEDIA_BUS_TYPE_PARALLEL) for ov5642/ov5640. i.MX53 and
i.MX6UL only supports parallel csi interface. Fix below CHECK_DTBS
warnings:
arm/boot/dts/nxp/imx/imx53-smd.dtb: ov5642@3c (ovti,ov5642): port:endpoint: 'bus-type' is a required property
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
arch/arm/boot/dts/nxp/imx/imx53-smd.dts | 2 ++
arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi | 1 +
2 files changed, 3 insertions(+)
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-smd.dts b/arch/arm/boot/dts/nxp/imx/imx53-smd.dts
index a1e19f9709b2c..8c02731c7ba9d 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-smd.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-smd.dts
@@ -5,6 +5,7 @@
/dts-v1/;
#include <dt-bindings/input/input.h>
+#include <dt-bindings/media/video-interfaces.h>
#include "imx53.dtsi"
/ {
@@ -314,6 +315,7 @@ camera: ov5642@3c {
port {
ov5642_to_ipu_csi0: endpoint {
remote-endpoint = <&ipu_csi0_from_parallel_sensor>;
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
bus-width = <8>;
hsync-active = <1>;
vsync-active = <1>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi
index 3d147b160ecf1..32afe4130e211 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi
@@ -217,6 +217,7 @@ camera@3c {
port {
ov5640_to_parallel: endpoint {
remote-endpoint = <¶llel_from_ov5640>;
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
bus-width = <8>;
data-shift = <2>; /* lines 9:2 are used */
hsync-active = <0>;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 5/6] ARM: dts: imx: replace undocumented compatible string edt,edt-ft5x06 with edt,edt-ft5206
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20260521-imx25_dts_simple_warning_2-v2-0-c6557df516a9@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
The edt,edt-ft5x06 compatible is not referenced in
drivers/input/touchscreen/edt-ft5x06.c and is not documented.
There is no publicly available datasheet or binding information that
distinguishes edt-ft5206/ft5306/ft5406 variants and the driver treats these
FT5x06-family controllers with the same configuration model. So switch to
the lowest common and documented baseline compatible edt,edt-ft5206.
Fix below CHECK_DTBS warnings:
arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dtb: /soc/bus@60000000/i2c@63fc8000/touchscreen@38: failed to match any schema with compatible: ['edt,edt-ft5x06']
ABI impact consideration:
Not affect Linux kernel. The I2C subsystem uses a legacy fallback mechanism
where it strips the vendor prefix from the compatible string to derive the
client name, resulting in edt-ft5x06
{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
After this, the driver was actively binding to these devices based on the
compatible string.
Known user (U-Boot) does not parse or use edt,edt-ft* touchscreen
compatibles.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v2
- update commit about ABI impact base on feedback from sashiko AI
- add missed change in imx6qdl-nitrogen6_som2.dtsi (sashiko AI)
Change binding doc discuss at
- https://lore.kernel.org/imx/aasmQiZJO2gSKzNH@lizhi-Precision-Tower-5810/
---
arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts | 2 +-
arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts | 2 +-
14 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
index 2acbc86cabb31..aa1c7e5012c6a 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-m53menlo.dts
@@ -248,7 +248,7 @@ &i2c1 {
status = "okay";
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_edt_ft5x06>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
index 872cf7e16f20c..6a1063c455f0c 100644
--- a/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx53-tx53-x03x.dts
@@ -201,7 +201,7 @@ sgtl5000: codec@a {
};
polytouch: edt-ft5x06@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_edt_ft5x06_1>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts b/arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts
index 0225a621ec7a9..ccf6a048c9184 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-var-dt6customboard.dts
@@ -169,7 +169,7 @@ &i2c3 {
status = "okay";
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi
index 610b2a72fe825..cebfd622df688 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nit6xlite.dtsi
@@ -256,7 +256,7 @@ touchscreen@4 {
};
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
index ef0c26688446e..f8a7218b13ef2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_max.dtsi
@@ -405,7 +405,7 @@ touchscreen@4 {
};
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi
index 03fe053880ca6..fb1c923c46bca 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6_som2.dtsi
@@ -326,7 +326,7 @@ touchscreen@4 {
};
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi
index 6a353a99e13da..9fe52e0ca7aa2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-nitrogen6x.dtsi
@@ -333,7 +333,7 @@ touchscreen@4 {
};
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
index c39a9ebdaba1c..ca4cb986efbc2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi
@@ -217,7 +217,7 @@ &i2c2 {
status = "okay";
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio5>;
interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
index ec1528ff3ea01..fe25934e06b1f 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-tx6.dtsi
@@ -292,7 +292,7 @@ sgtl5000: sgtl5000@a {
};
polytouch: edt-ft5x06@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_edt_ft5x06>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts
index bf7dbb4f1f3ed..e99ba04216b86 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-hobbit.dts
@@ -62,7 +62,7 @@ &i2c3 {
status = "okay";
polytouch: touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts
index 6cfc943a8fa3e..f79090fb2e6e2 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-pico-pi.dts
@@ -65,7 +65,7 @@ &i2c3 {
status = "okay";
polytouch: touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
interrupt-parent = <&gpio1>;
interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
index 1992dfb53b45c..192c6a95ae589 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi
@@ -317,7 +317,7 @@ sgtl5000: codec@a {
};
polytouch: polytouch@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_edt_ft5x06>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts
index 347dd0fe4f82e..fca8aab9d8507 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico-dwarf.dts
@@ -70,7 +70,7 @@ pca9554: io-expander@25 {
};
touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_touchscreen>;
diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts b/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts
index 62221131336f1..673bbe49de525 100644
--- a/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts
+++ b/arch/arm/boot/dts/nxp/imx/imx7d-pico-pi.dts
@@ -49,7 +49,7 @@ sgtl5000: codec@a {
&i2c4 {
polytouch: touchscreen@38 {
- compatible = "edt,edt-ft5x06";
+ compatible = "edt,edt-ft5206";
reg = <0x38>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_touchscreen>;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 6/6] ARM: dts: imx6-display5: replace marvell,88E1510 with ethernet-phy-ieee802.3-c22
From: Frank.Li @ 2026-05-21 19:15 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, Frank Li
In-Reply-To: <20260521-imx25_dts_simple_warning_2-v2-0-c6557df516a9@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Replace the vendor-specific PHY compatible string with the generic
ethernet-phy-ieee802.3-c22 compatible.
The marvell,88E1510 compatible is listed in whitelist_phys[] and is
never matched against a PHY driver. PHY devices are expected to use
the generic ethernet-phy-ieee802.3-c22 compatible unless a specific
MDIO driver match is required.
The 88E1510 is compatible with Clause 22 PHY devices, so use the
generic compatible string instead.
Fix below CHECK_DTBS warnings:
arch/arm/boot/dts/nxp/imx/imx6q-display5-tianma-tm070-1280x768.dtb: /soc/bus@2100000/ethernet@2188000/mdio/ethernet-phy@0: failed to match any schema with compatible: ['marvell,88E1510']
Known other user (uboot) did not use marvell,88E1510.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi b/arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi
index 4e448b4810f27..21e8bbdab4e69 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6q-display5.dtsi
@@ -208,7 +208,7 @@ mdio {
#address-cells = <1>;
#size-cells = <0>;
ethernet_phy0: ethernet-phy@0 {
- compatible = "marvell,88E1510";
+ compatible = "ethernet-phy-ieee802.3-c22";
device_type = "ethernet-phy";
/* Set LED0 control: */
/* On - Link, Blink - Activity, Off - No Link */
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox