From 73c3b40e536d9cb624db90b460bc384147576a57 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 20 Jul 2026 17:10:33 -0400 Subject: arm64: dts: imx8qm-ss-conn: add usbotg3 iommu information Add usbotg3 iommu information. Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi index ccf9f510e0f8..1370a571153a 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi @@ -32,3 +32,7 @@ compatible = "fsl,imx8qm-usdhc", "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc"; iommus = <&smmu 0x11 0x7f80>; }; + +&usbotg3_cdns3 { + iommus = <&smmu 0x4 0x7f80>; +}; -- cgit v1.2.3 From bc2f1c482286f5bd236ba42f438ab327b1b06c49 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 20 Jul 2026 17:10:34 -0400 Subject: arm64: dts: imx8qm-ss-conn: Add HSIC usb@5b0e0000 node Add usb@5b0e0000 and related node for i.MX8QM. Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi index 1370a571153a..c7063aaac4a3 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi @@ -4,6 +4,40 @@ * Dong Aisheng */ +&{/} { + usbphynop2: usbphynop2 { + compatible = "usb-nop-xceiv"; + clocks = <&usb2_lpcg IMX_LPCG_CLK_7>; + clock-names = "main_clk"; + power-domains = <&pd IMX_SC_R_USB_0_PHY>; + status = "disabled"; + }; +}; + +&conn_subsys { + usbh1: usb@5b0e0000 { + compatible = "fsl,imx7ulp-usb", "fsl,imx6ul-usb", "fsl,imx27-usb"; + reg = <0x5b0e0000 0x200>; + interrupt-parent = <&gic>; + interrupts = ; + phy_type = "hsic"; + dr_mode = "host"; + clocks = <&usb2_lpcg IMX_LPCG_CLK_6>; + ahb-burst-config = <0x0>; + tx-burst-size-dword = <0x10>; + rx-burst-size-dword = <0x10>; + power-domains = <&pd IMX_SC_R_USB_1>; + fsl,usbphy = <&usbphynop2>; + fsl,usbmisc = <&usbmisc2 0>; + }; + + usbmisc2: usbmisc@5b0e0200 { + compatible = "fsl,imx7ulp-usbmisc", "fsl,imx7d-usbmisc", "fsl,imx6q-usbmisc"; + #index-cells = <1>; + reg = <0x5b0e0200 0x200>; + }; +}; + &usbphy1 { compatible = "fsl,imx8qm-usbphy", "fsl,imx7ulp-usbphy"; }; -- cgit v1.2.3 From 264480ac044bd4d51489ccb7b17b7b50e2e5bf3f Mon Sep 17 00:00:00 2001 From: Joseph Guo Date: Thu, 23 Jul 2026 16:13:21 +0900 Subject: arm64: dts: imx93-11x11-frdm: factor out common parts into dtsi The i.MX93 Wireless FRDM board reuses most of the i.MX93 FRDM board. To avoid duplication and DTS-to-DTS includes, extract common hardware definitions from imx93-11x11-frdm.dts into imx93-11x11-frdm-common.dtsi to allow the common description shared by both boards. The FRDM-IMX93 board-specific .dts now includes the common dtsi and only contains board-specific overrides. Signed-off-by: Joseph Guo Signed-off-by: Frank Li --- .../dts/freescale/imx93-11x11-frdm-common.dtsi | 680 +++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts | 679 +------------------- 2 files changed, 686 insertions(+), 673 deletions(-) create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi new file mode 100644 index 000000000000..5c8fdd77ec15 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi @@ -0,0 +1,680 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +#include + +/ { + aliases { + can0 = &flexcan2; + ethernet0 = &fec; + ethernet1 = &eqos; + i2c0 = &lpi2c1; + i2c1 = &lpi2c2; + i2c2 = &lpi2c3; + mmc0 = &usdhc1; /* EMMC */ + mmc1 = &usdhc2; /* uSD */ + rtc0 = &pcf2131; + serial0 = &lpuart1; + serial4 = &lpuart5; + }; + + chosen { + stdout-path = &lpuart1; + }; + + flexcan2_phy: can-phy { + compatible = "nxp,tja1051"; + #phy-cells = <0>; + max-bitrate = <5000000>; + silent-gpios = <&pcal6524 23 GPIO_ACTIVE_HIGH>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-k2 { + label = "Button K2"; + linux,code = ; + gpios = <&pcal6524 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + interrupt-parent = <&pcal6524>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + }; + + button-k3 { + label = "Button K3"; + linux,code = ; + gpios = <&pcal6524 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + interrupt-parent = <&pcal6524>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; + }; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + compatible = "regulator-fixed"; + off-on-delay-us = <12000>; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + pinctrl-names = "default"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "VSD_3V3"; + vin-supply = <&buck4>; + gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reserved-memory { + ranges; + #address-cells = <2>; + #size-cells = <2>; + + linux,cma { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x80000000 0 0x30000000>; + reusable; + size = <0 0x10000000>; + linux,cma-default; + }; + + rsc_table: rsc-table@2021e000 { + reg = <0 0x2021e000 0 0x1000>; + no-map; + }; + + vdev0vring0: vdev0vring0@a4000000 { + reg = <0 0xa4000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@a4008000 { + reg = <0 0xa4008000 0 0x8000>; + no-map; + }; + + vdev1vring0: vdev1vring0@a4010000 { + reg = <0 0xa4010000 0 0x8000>; + no-map; + }; + + vdev1vring1: vdev1vring1@a4018000 { + reg = <0 0xa4018000 0 0x8000>; + no-map; + }; + + vdevbuffer: vdevbuffer@a4020000 { + compatible = "shared-dma-pool"; + reg = <0 0xa4020000 0 0x100000>; + no-map; + }; + }; +}; + +&adc1 { + vref-supply = <&buck5>; + status = "okay"; +}; + +&mu1 { + status = "okay"; +}; + +&cm33 { + mboxes = <&mu1 0 1>, + <&mu1 1 1>, + <&mu1 3 1>; + mbox-names = "tx", "rx", "rxdb"; + memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; + status = "okay"; +}; + +&eqos { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_eqos>; + pinctrl-1 = <&pinctrl_eqos_sleep>; + phy-handle = <ðphy1>; + phy-mode = "rgmii-id"; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <5000000>; + + ethphy1: ethernet-phy@1 { + reg = <1>; + reset-assert-us = <10000>; + reset-deassert-us = <80000>; + reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>; + realtek,clkout-disable; + }; + }; +}; + +&fec { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_fec>; + pinctrl-1 = <&pinctrl_fec_sleep>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy2>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <5000000>; + + ethphy2: ethernet-phy@2 { + reg = <2>; + reset-assert-us = <10000>; + reset-deassert-us = <80000>; + reset-gpios = <&pcal6524 16 GPIO_ACTIVE_LOW>; + realtek,clkout-disable; + }; + }; +}; + +&flexcan2 { + phys = <&flexcan2_phy>; + pinctrl-0 = <&pinctrl_flexcan2>; + pinctrl-1 = <&pinctrl_flexcan2_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; + +&lpi2c1 { + clock-frequency = <400000>; + pinctrl-0 = <&pinctrl_lpi2c1>; + pinctrl-names = "default"; + status = "okay"; +}; + +&lpi2c2 { + clock-frequency = <400000>; + pinctrl-0 = <&pinctrl_lpi2c2>; + pinctrl-names = "default"; + status = "okay"; + + pcal6524: gpio@22 { + compatible = "nxp,pcal6524"; + reg = <0x22>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio3>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + pinctrl-0 = <&pinctrl_pcal6524>; + pinctrl-names = "default"; + /* does not boot with supplier set, because it is the bucks interrupt parent */ + /* vcc-supply = <&buck4>; */ + }; + + pmic@25 { + compatible = "nxp,pca9451a"; + reg = <0x25>; + interrupt-parent = <&pcal6524>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; + + regulators { + + buck1: BUCK1 { + regulator-name = "VDD_SOC_0V8"; + regulator-min-microvolt = <610000>; + regulator-max-microvolt = <950000>; + regulator-always-on; + regulator-boot-on; + regulator-ramp-delay = <3125>; + }; + + buck2: BUCK2 { + regulator-name = "LPD4_x_VDDQ_0V6"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <670000>; + regulator-always-on; + regulator-boot-on; + regulator-ramp-delay = <3125>; + }; + + buck4: BUCK4 { + regulator-name = "VDD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + buck5: BUCK5 { + regulator-name = "VDD_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + buck6: BUCK6 { + regulator-name = "LPD4_x_VDD2_1V1"; + regulator-min-microvolt = <1060000>; + regulator-max-microvolt = <1140000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo1: LDO1 { + regulator-name = "NVCC_BBSM_1V8"; + regulator-min-microvolt = <1620000>; + regulator-max-microvolt = <1980000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo4: LDO4 { + regulator-name = "VDD_ANA_0V8"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <840000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo5: LDO5 { + regulator-name = "NVCC_SD"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; + + eeprom: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + pagesize = <64>; + vcc-supply = <&buck4>; + }; +}; + +&lpi2c3 { + clock-frequency = <400000>; + pinctrl-0 = <&pinctrl_lpi2c3>; + pinctrl-names = "default"; + status = "okay"; + + ptn5110: tcpc@50 { + compatible = "nxp,ptn5110", "tcpci"; + reg = <0x50>; + interrupt-parent = <&gpio3>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + + typec1_con: connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB-C"; + op-sink-microwatt = <15000000>; + power-role = "dual"; + self-powered; + sink-pdos = ; + source-pdos = ; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + typec1_dr_sw: endpoint { + remote-endpoint = <&usb1_drd_sw>; + }; + }; + }; + }; + }; + + pcf2131: rtc@53 { + compatible = "nxp,pcf2131"; + reg = <0x53>; + interrupt-parent = <&pcal6524>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&lpuart1 { /* console */ + pinctrl-0 = <&pinctrl_uart1>; + pinctrl-names = "default"; + status = "okay"; +}; + +&lpuart5 { + pinctrl-0 = <&pinctrl_uart5>; + pinctrl-names = "default"; + status = "okay"; + + uart-has-rtscts; + + bluetooth: bluetooth { + compatible = "nxp,88w8987-bt"; + }; +}; + +&usbotg1 { + adp-disable; + disable-over-current; + dr_mode = "otg"; + hnp-disable; + srp-disable; + usb-role-switch; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; + status = "okay"; + + port { + usb1_drd_sw: endpoint { + remote-endpoint = <&typec1_dr_sw>; + }; + }; +}; + +&usbotg2 { + disable-over-current; + dr_mode = "host"; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; + status = "okay"; +}; + +&usdhc1 { + bus-width = <8>; + non-removable; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + vmmc-supply = <&buck4>; + status = "okay"; +}; + +&usdhc2 { + bus-width = <4>; + cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; + no-mmc; + no-sdio; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>; + pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; + vmmc-supply = <®_usdhc2_vmmc>; + status = "okay"; +}; + +&wdog3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; + +&iomuxc { + + pinctrl_eqos: eqosgrp { + fsl,pins = < + MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e + MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e + MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e + MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e + MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e + MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e + MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x58e + MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e + MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e + MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e + MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e + MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e + MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e + MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e + >; + }; + + pinctrl_eqos_sleep: eqossleepgrp { + fsl,pins = < + MX93_PAD_ENET1_MDC__GPIO4_IO00 0x31e + MX93_PAD_ENET1_MDIO__GPIO4_IO01 0x31e + MX93_PAD_ENET1_RD0__GPIO4_IO10 0x31e + MX93_PAD_ENET1_RD1__GPIO4_IO11 0x31e + MX93_PAD_ENET1_RD2__GPIO4_IO12 0x31e + MX93_PAD_ENET1_RD3__GPIO4_IO13 0x31e + MX93_PAD_ENET1_RXC__GPIO4_IO09 0x31e + MX93_PAD_ENET1_RX_CTL__GPIO4_IO08 0x31e + MX93_PAD_ENET1_TD0__GPIO4_IO05 0x31e + MX93_PAD_ENET1_TD1__GPIO4_IO04 0x31e + MX93_PAD_ENET1_TD2__GPIO4_IO03 0x31e + MX93_PAD_ENET1_TD3__GPIO4_IO02 0x31e + MX93_PAD_ENET1_TXC__GPIO4_IO07 0x31e + MX93_PAD_ENET1_TX_CTL__GPIO4_IO06 0x31e + >; + }; + + pinctrl_fec: fecgrp { + fsl,pins = < + MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e + MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e + MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e + MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e + MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e + MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e + MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x58e + MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e + MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e + MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e + MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e + MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e + MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x58e + MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e + >; + }; + + pinctrl_fec_sleep: fecsleepgrp { + fsl,pins = < + MX93_PAD_ENET2_MDC__GPIO4_IO14 0x51e + MX93_PAD_ENET2_MDIO__GPIO4_IO15 0x51e + MX93_PAD_ENET2_RD0__GPIO4_IO24 0x51e + MX93_PAD_ENET2_RD1__GPIO4_IO25 0x51e + MX93_PAD_ENET2_RD2__GPIO4_IO26 0x51e + MX93_PAD_ENET2_RD3__GPIO4_IO27 0x51e + MX93_PAD_ENET2_RXC__GPIO4_IO23 0x51e + MX93_PAD_ENET2_RX_CTL__GPIO4_IO22 0x51e + MX93_PAD_ENET2_TD0__GPIO4_IO19 0x51e + MX93_PAD_ENET2_TD1__GPIO4_IO18 0x51e + MX93_PAD_ENET2_TD2__GPIO4_IO17 0x51e + MX93_PAD_ENET2_TD3__GPIO4_IO16 0x51e + MX93_PAD_ENET2_TXC__GPIO4_IO21 0x51e + MX93_PAD_ENET2_TX_CTL__GPIO4_IO20 0x51e + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX93_PAD_GPIO_IO25__CAN2_TX 0x139e + MX93_PAD_GPIO_IO27__CAN2_RX 0x139e + >; + }; + + pinctrl_flexcan2_sleep: flexcan2sleepgrp { + fsl,pins = < + MX93_PAD_GPIO_IO25__GPIO2_IO25 0x31e + MX93_PAD_GPIO_IO27__GPIO2_IO27 0x31e + >; + }; + + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c2: lpi2c2grp { + fsl,pins = < + MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e + MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c3: lpi2c3grp { + fsl,pins = < + MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e + MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e + >; + }; + + pinctrl_pcal6524: pcal6524grp { + fsl,pins = < + MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { + fsl,pins = < + MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX93_PAD_UART1_RXD__LPUART1_RX 0x31e + MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e + MX93_PAD_DAP_TDI__LPUART5_RX 0x31e + MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e + MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582 + MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382 + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382 + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382 + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382 + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382 + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382 + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382 + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382 + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382 + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582 + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e + MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe + MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e + >; + }; + + pinctrl_usdhc2_gpio_sleep: usdhc2gpiosleepgrp { + fsl,pins = < + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x51e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 + MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e + MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; + + /* need to config the SION for data and cmd pad, refer to ERR052021 */ + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe + MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; + + pinctrl_usdhc2_sleep: usdhc2-sleepgrp { + fsl,pins = < + MX93_PAD_SD2_CLK__GPIO3_IO01 0x51e + MX93_PAD_SD2_CMD__GPIO3_IO02 0x51e + MX93_PAD_SD2_DATA0__GPIO3_IO03 0x51e + MX93_PAD_SD2_DATA1__GPIO3_IO04 0x51e + MX93_PAD_SD2_DATA2__GPIO3_IO05 0x51e + MX93_PAD_SD2_DATA3__GPIO3_IO06 0x51e + MX93_PAD_SD2_VSELECT__GPIO3_IO19 0x51e + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX93_PAD_WDOG_ANY__WDOG1_WDOG_ANY 0x31e + >; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts index bd14ba28690c..8034992a73c7 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts @@ -1,71 +1,14 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) + /dts-v1/; -#include #include "imx93.dtsi" +#include "imx93-11x11-frdm-common.dtsi" / { compatible = "fsl,imx93-11x11-frdm", "fsl,imx93"; model = "NXP i.MX93 11X11 FRDM board"; - aliases { - can0 = &flexcan2; - ethernet0 = &fec; - ethernet1 = &eqos; - i2c0 = &lpi2c1; - i2c1 = &lpi2c2; - i2c2 = &lpi2c3; - mmc0 = &usdhc1; /* EMMC */ - mmc1 = &usdhc2; /* uSD */ - rtc0 = &pcf2131; - serial0 = &lpuart1; - serial4 = &lpuart5; - }; - - chosen { - stdout-path = &lpuart1; - }; - - flexcan2_phy: can-phy { - compatible = "nxp,tja1051"; - #phy-cells = <0>; - max-bitrate = <5000000>; - silent-gpios = <&pcal6524 23 GPIO_ACTIVE_HIGH>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - button-k2 { - label = "Button K2"; - linux,code = ; - gpios = <&pcal6524 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - interrupt-parent = <&pcal6524>; - interrupts = <5 IRQ_TYPE_EDGE_FALLING>; - }; - - button-k3 { - label = "Button K3"; - linux,code = ; - gpios = <&pcal6524 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - interrupt-parent = <&pcal6524>; - interrupts = <6 IRQ_TYPE_EDGE_FALLING>; - }; - }; - - reg_usdhc2_vmmc: regulator-usdhc2 { - compatible = "regulator-fixed"; - off-on-delay-us = <12000>; - pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; - pinctrl-names = "default"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "VSD_3V3"; - vin-supply = <&buck4>; - gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; - reg_usdhc3_vmmc: regulator-usdhc3 { compatible = "regulator-fixed"; regulator-name = "VPCIe_3V3"; @@ -76,51 +19,6 @@ enable-active-high; }; - reserved-memory { - ranges; - #address-cells = <2>; - #size-cells = <2>; - - linux,cma { - compatible = "shared-dma-pool"; - alloc-ranges = <0 0x80000000 0 0x30000000>; - reusable; - size = <0 0x10000000>; - linux,cma-default; - }; - - rsc_table: rsc-table@2021e000 { - reg = <0 0x2021e000 0 0x1000>; - no-map; - }; - - vdev0vring0: vdev0vring0@a4000000 { - reg = <0 0xa4000000 0 0x8000>; - no-map; - }; - - vdev0vring1: vdev0vring1@a4008000 { - reg = <0 0xa4008000 0 0x8000>; - no-map; - }; - - vdev1vring0: vdev1vring0@a4010000 { - reg = <0 0xa4010000 0 0x8000>; - no-map; - }; - - vdev1vring1: vdev1vring1@a4018000 { - reg = <0 0xa4018000 0 0x8000>; - no-map; - }; - - vdevbuffer: vdevbuffer@a4020000 { - compatible = "shared-dma-pool"; - reg = <0 0xa4020000 0 0x100000>; - no-map; - }; - }; - sound-mqs { compatible = "fsl,imx-audio-mqs"; model = "mqs-audio"; @@ -134,87 +32,13 @@ }; }; -&adc1 { - vref-supply = <&buck5>; - status = "okay"; -}; - -&mu1 { - status = "okay"; -}; - -&cm33 { - mboxes = <&mu1 0 1>, - <&mu1 1 1>, - <&mu1 3 1>; - mbox-names = "tx", "rx", "rxdb"; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, - <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; - status = "okay"; -}; - -&eqos { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&pinctrl_eqos>; - pinctrl-1 = <&pinctrl_eqos_sleep>; - phy-handle = <ðphy1>; - phy-mode = "rgmii-id"; - status = "okay"; - - mdio { - compatible = "snps,dwmac-mdio"; - #address-cells = <1>; - #size-cells = <0>; - clock-frequency = <5000000>; - - ethphy1: ethernet-phy@1 { - reg = <1>; - reset-assert-us = <10000>; - reset-deassert-us = <80000>; - reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>; - realtek,clkout-disable; - }; - }; -}; - -&fec { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&pinctrl_fec>; - pinctrl-1 = <&pinctrl_fec_sleep>; - phy-mode = "rgmii-id"; - phy-handle = <ðphy2>; - fsl,magic-packet; - status = "okay"; - - mdio { - #address-cells = <1>; - #size-cells = <0>; - clock-frequency = <5000000>; - - ethphy2: ethernet-phy@2 { - reg = <2>; - reset-assert-us = <10000>; - reset-deassert-us = <80000>; - reset-gpios = <&pcal6524 16 GPIO_ACTIVE_LOW>; - realtek,clkout-disable; - }; - }; -}; - -&flexcan2 { - phys = <&flexcan2_phy>; - pinctrl-0 = <&pinctrl_flexcan2>; - pinctrl-1 = <&pinctrl_flexcan2_sleep>; - pinctrl-names = "default", "sleep"; - status = "okay"; +&bluetooth { + device-wakeup-gpios = <&pcal6408 3 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pcal6524 19 GPIO_ACTIVE_LOW>; + vcc-supply = <®_usdhc3_vmmc>; }; &lpi2c1 { - clock-frequency = <400000>; - pinctrl-0 = <&pinctrl_lpi2c1>; - pinctrl-names = "default"; - status = "okay"; - pcal6408: gpio@20 { compatible = "nxp,pcal6408"; reg = <0x20>; @@ -224,179 +48,6 @@ }; }; -&lpi2c2 { - clock-frequency = <400000>; - pinctrl-0 = <&pinctrl_lpi2c2>; - pinctrl-names = "default"; - status = "okay"; - - pcal6524: gpio@22 { - compatible = "nxp,pcal6524"; - reg = <0x22>; - #interrupt-cells = <2>; - interrupt-controller; - interrupt-parent = <&gpio3>; - interrupts = <27 IRQ_TYPE_LEVEL_LOW>; - #gpio-cells = <2>; - gpio-controller; - pinctrl-0 = <&pinctrl_pcal6524>; - pinctrl-names = "default"; - /* does not boot with supplier set, because it is the bucks interrupt parent */ - /* vcc-supply = <&buck4>; */ - }; - - pmic@25 { - compatible = "nxp,pca9451a"; - reg = <0x25>; - interrupt-parent = <&pcal6524>; - interrupts = <11 IRQ_TYPE_EDGE_FALLING>; - - regulators { - - buck1: BUCK1 { - regulator-name = "VDD_SOC_0V8"; - regulator-min-microvolt = <610000>; - regulator-max-microvolt = <950000>; - regulator-always-on; - regulator-boot-on; - regulator-ramp-delay = <3125>; - }; - - buck2: BUCK2 { - regulator-name = "LPD4_x_VDDQ_0V6"; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <670000>; - regulator-always-on; - regulator-boot-on; - regulator-ramp-delay = <3125>; - }; - - buck4: BUCK4 { - regulator-name = "VDD_3V3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - }; - - buck5: BUCK5 { - regulator-name = "VDD_1V8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - regulator-boot-on; - }; - - buck6: BUCK6 { - regulator-name = "LPD4_x_VDD2_1V1"; - regulator-min-microvolt = <1060000>; - regulator-max-microvolt = <1140000>; - regulator-always-on; - regulator-boot-on; - }; - - ldo1: LDO1 { - regulator-name = "NVCC_BBSM_1V8"; - regulator-min-microvolt = <1620000>; - regulator-max-microvolt = <1980000>; - regulator-always-on; - regulator-boot-on; - }; - - ldo4: LDO4 { - regulator-name = "VDD_ANA_0V8"; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <840000>; - regulator-always-on; - regulator-boot-on; - }; - - ldo5: LDO5 { - regulator-name = "NVCC_SD"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - }; - }; - }; - - eeprom: eeprom@50 { - compatible = "atmel,24c256"; - reg = <0x50>; - pagesize = <64>; - vcc-supply = <&buck4>; - }; -}; - -&lpi2c3 { - clock-frequency = <400000>; - pinctrl-0 = <&pinctrl_lpi2c3>; - pinctrl-names = "default"; - status = "okay"; - - ptn5110: tcpc@50 { - compatible = "nxp,ptn5110", "tcpci"; - reg = <0x50>; - interrupt-parent = <&gpio3>; - interrupts = <27 IRQ_TYPE_LEVEL_LOW>; - - typec1_con: connector { - compatible = "usb-c-connector"; - data-role = "dual"; - label = "USB-C"; - op-sink-microwatt = <15000000>; - power-role = "dual"; - self-powered; - sink-pdos = ; - source-pdos = ; - try-power-role = "sink"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - typec1_dr_sw: endpoint { - remote-endpoint = <&usb1_drd_sw>; - }; - }; - }; - }; - }; - - pcf2131: rtc@53 { - compatible = "nxp,pcf2131"; - reg = <0x53>; - interrupt-parent = <&pcal6524>; - interrupts = <1 IRQ_TYPE_EDGE_FALLING>; - }; -}; - -&lpuart1 { /* console */ - pinctrl-0 = <&pinctrl_uart1>; - pinctrl-names = "default"; - status = "okay"; -}; - -&lpuart5 { - pinctrl-0 = <&pinctrl_uart5>; - pinctrl-names = "default"; - status = "okay"; - - uart-has-rtscts; - - bluetooth { - compatible = "nxp,88w8987-bt"; - device-wakeup-gpios = <&pcal6408 3 GPIO_ACTIVE_HIGH>; - reset-gpios = <&pcal6524 19 GPIO_ACTIVE_LOW>; - vcc-supply = <®_usdhc3_vmmc>; - }; -}; - &mqs1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mqs1>; @@ -418,57 +69,6 @@ status = "okay"; }; -&usbotg1 { - adp-disable; - disable-over-current; - dr_mode = "otg"; - hnp-disable; - srp-disable; - usb-role-switch; - samsung,picophy-dc-vol-level-adjust = <7>; - samsung,picophy-pre-emp-curr-control = <3>; - status = "okay"; - - port { - usb1_drd_sw: endpoint { - remote-endpoint = <&typec1_dr_sw>; - }; - }; -}; - -&usbotg2 { - disable-over-current; - dr_mode = "host"; - samsung,picophy-dc-vol-level-adjust = <7>; - samsung,picophy-pre-emp-curr-control = <3>; - status = "okay"; -}; - -&usdhc1 { - bus-width = <8>; - non-removable; - pinctrl-0 = <&pinctrl_usdhc1>; - pinctrl-1 = <&pinctrl_usdhc1_100mhz>; - pinctrl-2 = <&pinctrl_usdhc1_200mhz>; - pinctrl-names = "default", "state_100mhz", "state_200mhz"; - vmmc-supply = <&buck4>; - status = "okay"; -}; - -&usdhc2 { - bus-width = <4>; - cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; - no-mmc; - no-sdio; - pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; - pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; - pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; - pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>; - pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; - vmmc-supply = <®_usdhc2_vmmc>; - status = "okay"; -}; - &usdhc3 { bus-width = <4>; keep-power-in-suspend; @@ -483,126 +83,7 @@ status = "okay"; }; -&wdog3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_wdog>; - fsl,ext-reset-output; - status = "okay"; -}; - &iomuxc { - - pinctrl_eqos: eqosgrp { - fsl,pins = < - MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e - MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e - MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e - MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e - MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e - MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e - MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x58e - MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e - MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e - MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e - MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e - MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e - MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e - MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e - >; - }; - - pinctrl_eqos_sleep: eqossleepgrp { - fsl,pins = < - MX93_PAD_ENET1_MDC__GPIO4_IO00 0x31e - MX93_PAD_ENET1_MDIO__GPIO4_IO01 0x31e - MX93_PAD_ENET1_RD0__GPIO4_IO10 0x31e - MX93_PAD_ENET1_RD1__GPIO4_IO11 0x31e - MX93_PAD_ENET1_RD2__GPIO4_IO12 0x31e - MX93_PAD_ENET1_RD3__GPIO4_IO13 0x31e - MX93_PAD_ENET1_RXC__GPIO4_IO09 0x31e - MX93_PAD_ENET1_RX_CTL__GPIO4_IO08 0x31e - MX93_PAD_ENET1_TD0__GPIO4_IO05 0x31e - MX93_PAD_ENET1_TD1__GPIO4_IO04 0x31e - MX93_PAD_ENET1_TD2__GPIO4_IO03 0x31e - MX93_PAD_ENET1_TD3__GPIO4_IO02 0x31e - MX93_PAD_ENET1_TXC__GPIO4_IO07 0x31e - MX93_PAD_ENET1_TX_CTL__GPIO4_IO06 0x31e - >; - }; - - pinctrl_fec: fecgrp { - fsl,pins = < - MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e - MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e - MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e - MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e - MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e - MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e - MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x58e - MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e - MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e - MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e - MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e - MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e - MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x58e - MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e - >; - }; - - pinctrl_fec_sleep: fecsleepgrp { - fsl,pins = < - MX93_PAD_ENET2_MDC__GPIO4_IO14 0x51e - MX93_PAD_ENET2_MDIO__GPIO4_IO15 0x51e - MX93_PAD_ENET2_RD0__GPIO4_IO24 0x51e - MX93_PAD_ENET2_RD1__GPIO4_IO25 0x51e - MX93_PAD_ENET2_RD2__GPIO4_IO26 0x51e - MX93_PAD_ENET2_RD3__GPIO4_IO27 0x51e - MX93_PAD_ENET2_RXC__GPIO4_IO23 0x51e - MX93_PAD_ENET2_RX_CTL__GPIO4_IO22 0x51e - MX93_PAD_ENET2_TD0__GPIO4_IO19 0x51e - MX93_PAD_ENET2_TD1__GPIO4_IO18 0x51e - MX93_PAD_ENET2_TD2__GPIO4_IO17 0x51e - MX93_PAD_ENET2_TD3__GPIO4_IO16 0x51e - MX93_PAD_ENET2_TXC__GPIO4_IO21 0x51e - MX93_PAD_ENET2_TX_CTL__GPIO4_IO20 0x51e - >; - }; - - pinctrl_flexcan2: flexcan2grp { - fsl,pins = < - MX93_PAD_GPIO_IO25__CAN2_TX 0x139e - MX93_PAD_GPIO_IO27__CAN2_RX 0x139e - >; - }; - - pinctrl_flexcan2_sleep: flexcan2sleepgrp { - fsl,pins = < - MX93_PAD_GPIO_IO25__GPIO2_IO25 0x31e - MX93_PAD_GPIO_IO27__GPIO2_IO27 0x31e - >; - }; - - pinctrl_lpi2c1: lpi2c1grp { - fsl,pins = < - MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e - MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e - >; - }; - - pinctrl_lpi2c2: lpi2c2grp { - fsl,pins = < - MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e - MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e - >; - }; - - pinctrl_lpi2c3: lpi2c3grp { - fsl,pins = < - MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e - MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e - >; - }; - pinctrl_mqs1: mqs1grp { fsl,pins = < MX93_PAD_PDM_CLK__MQS1_LEFT 0x31e @@ -610,149 +91,7 @@ >; }; - pinctrl_pcal6524: pcal6524grp { - fsl,pins = < - MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e - >; - }; - - pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { - fsl,pins = < - MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e - >; - }; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX93_PAD_UART1_RXD__LPUART1_RX 0x31e - MX93_PAD_UART1_TXD__LPUART1_TX 0x31e - >; - }; - - pinctrl_uart5: uart5grp { - fsl,pins = < - MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e - MX93_PAD_DAP_TDI__LPUART5_RX 0x31e - MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e - MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e - >; - }; - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc1: usdhc1grp { - fsl,pins = < - MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582 - MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382 - MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382 - MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382 - MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382 - MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382 - MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382 - MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382 - MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382 - MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382 - MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582 - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { - fsl,pins = < - MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e - MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e - MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e - MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e - MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e - MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e - MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e - MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e - MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e - MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e - MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { - fsl,pins = < - MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe - MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe - MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe - MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe - MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe - MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe - MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe - MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe - MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe - MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe - MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe - >; - }; - - pinctrl_usdhc2_gpio: usdhc2gpiogrp { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e - >; - }; - - pinctrl_usdhc2_gpio_sleep: usdhc2gpiosleepgrp { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 - MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e - MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe - MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - pinctrl_usdhc2_sleep: usdhc2-sleepgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__GPIO3_IO01 0x51e - MX93_PAD_SD2_CMD__GPIO3_IO02 0x51e - MX93_PAD_SD2_DATA0__GPIO3_IO03 0x51e - MX93_PAD_SD2_DATA1__GPIO3_IO04 0x51e - MX93_PAD_SD2_DATA2__GPIO3_IO05 0x51e - MX93_PAD_SD2_DATA3__GPIO3_IO06 0x51e - MX93_PAD_SD2_VSELECT__GPIO3_IO19 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ pinctrl_usdhc3: usdhc3grp { fsl,pins = < MX93_PAD_SD3_CLK__USDHC3_CLK 0x1582 @@ -798,10 +137,4 @@ MX93_PAD_SD3_DATA3__GPIO3_IO25 0x31e >; }; - - pinctrl_wdog: wdoggrp { - fsl,pins = < - MX93_PAD_WDOG_ANY__WDOG1_WDOG_ANY 0x31e - >; - }; }; -- cgit v1.2.3 From d9f4c2390151c091ee23b1669c11e22d39dcc63e Mon Sep 17 00:00:00 2001 From: Joseph Guo Date: Thu, 23 Jul 2026 16:13:22 +0900 Subject: dt-bindings: arm: fsl: Add i.MX93 Wireless FRDM board Add DT compatible string for NXP i.MX93 Wireless FRDM board. i.MX93 Wireless SiP is created by integrating i.MX93 and IW610 WLCSP (Wi-Fi + BLE + 802.15.4). And i.MX93 Wireless FRDM board with the i.MX93 Wireless SiP basically reuse the i.MX93 11x11 FRDM board, with some minor functional and pin connection differences. Acked-by: Krzysztof Kozlowski Signed-off-by: Joseph Guo Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 656f2596e1d5..6c356623dade 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1519,6 +1519,7 @@ properties: - fsl,imx93-11x11-frdm # i.MX93 11x11 FRDM Board - fsl,imx93-14x14-evk # i.MX93 14x14 EVK Board - fsl,imx93-wireless-evk # i.MX93 and IW610G WLCSP (Wi-Fi + BLE + 802.15.4) SiP EVK Board + - fsl,imx93-wireless-frdm # i.MX93 and IW610G WLCSP (Wi-Fi + BLE + 802.15.4) SiP FRDM Board - const: fsl,imx93 - description: i.MX94 based Boards -- cgit v1.2.3 From cac63565a186028ed6c6564c277910cdfe592828 Mon Sep 17 00:00:00 2001 From: Joseph Guo Date: Thu, 23 Jul 2026 16:13:23 +0900 Subject: arm64: dts: imx93: Add i.MX93 Wireless FRDM board support i.MX93 Wireless FRDM board(FRDM-IMX93W) is a low-cost and compact board featuring the i.MX93W applications processor. FRDM-IMX93W board basically reuse the FRDM-IMX93 board, with some minor functional and pin connection differences. Reuse the imx93-11x11-frdm-common.dtsi and add the board-specific changes. Here are the detailed differences between FRDM-IMX93 and FRDM-IMX93W board. Function differences: Function FRDM-IMX93W FRDM-IMX93 WIFI/BT IW610 in i.MX93W IW612 M.2 module MQS N Y M.2 N Y RPi 40-pin HDR Limited support(pin conflict) Y Pin connection differences: Function Signal name i.MX93W EVK i.MX93 EVK WIFI/BT SPI_FRM SAI1_TXFS (spi1.PCS0) GPIO_IO08 (spi3.PCS0) SPI_TXD SAI1_TXC (spi1.SIN) GPIO_IO09 (spi3.SIN) SPI_RXD SAI1_RXD0 (spi1.SOUT) GPIO_IO10 (spi3.SOUT) SPI_CLK SAI1_TXD0 (spi1.SCK) GPIO_IO11 (spi3.SCK) SPI_INT CCM_CLKO1 on-board IO expander NB_WAKE_IN PDM_CLK on-module IO expander WL_WAKE_IN PDM_BIT_STREAM0 on-module IO expander IND_RST_WL PDM_BIT_STREAM1 on-module IO expander IND_RST_NB GPIO_IO28 on-module IO expander PDn GPIO_IO29 on-module IO expander NB_WAKE_OUT GPIO_IO14 on-board IO expander WL_WAKE_OUT GPIO_IO15 CCM_CLKO1 I2C3 I2C3_SDA GPIO_IO00 GPIO_IO28 I2C3_SCL GPIO_IO01 GPIO_IO29 Signed-off-by: Joseph Guo Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 1 + arch/arm64/boot/dts/freescale/imx93w-frdm.dts | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx93w-frdm.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 95ae85ab4adf..8e6216b5c83a 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -695,6 +695,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla-mini-lvds-tm070jvhg33.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-var-dart-sonata.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-var-som-symphony.dtb dtb-$(CONFIG_ARCH_MXC) += imx93w-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx93w-frdm.dtb dtb-$(CONFIG_ARCH_MXC) += imx943-evk.dtb imx943-evk-pcie0-ep-dtbs += imx943-evk.dtb imx-pcie0-ep.dtbo diff --git a/arch/arm64/boot/dts/freescale/imx93w-frdm.dts b/arch/arm64/boot/dts/freescale/imx93w-frdm.dts new file mode 100644 index 000000000000..766e942fe663 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93w-frdm.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 NXP + */ + +/dts-v1/; + +#include "imx93w.dtsi" +#include "imx93-11x11-frdm-common.dtsi" + +/ { + model = "NXP i.MX93W FRDM board"; + compatible = "fsl,imx93-wireless-frdm", "fsl,imx93"; +}; + +&iomuxc { + pinctrl_lpi2c3: lpi2c3grp { + fsl,pins = < + MX93_PAD_GPIO_IO00__LPI2C3_SDA 0x40000b9e + MX93_PAD_GPIO_IO01__LPI2C3_SCL 0x40000b9e + >; + }; +}; -- cgit v1.2.3 From 232998b3286f02ab1defab7093480fcb584fcf31 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 1 Aug 2026 23:04:22 +0200 Subject: arm64: dts: freescale: Correct white-space style Correct a few white-space issues, like missing space before bracket '{' character or spurious space, which will be flagged by dt-check-style ("redundant-whitespace" warning). No functional changes. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Alexander Stein Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi | 2 +- arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi | 2 +- arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dts | 2 +- arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp.dtsi | 2 +- .../freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds0-tm070jvhg33.dtso | 2 +- .../freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds1-tm070jvhg33.dtso | 2 +- arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts | 4 ++-- arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 4 ++-- arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts | 2 +- arch/arm64/boot/dts/freescale/imx8qm-var-som-symphony.dts | 2 +- arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi | 6 +++--- arch/arm64/boot/dts/freescale/imx95.dtsi | 8 ++++---- arch/arm64/boot/dts/freescale/imx952.dtsi | 8 ++++---- arch/arm64/boot/dts/freescale/s32g2.dtsi | 2 +- arch/arm64/boot/dts/freescale/s32g3.dtsi | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi index ef62968590fa..ed8109326151 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi @@ -105,7 +105,7 @@ }; firmware { - optee: optee { + optee: optee { compatible = "linaro,optee-tz"; method = "smc"; status = "disabled"; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi index ea1d5b9c6bae..94e18357e37f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-beacon-baseboard.dtsi @@ -49,7 +49,7 @@ clock-frequency = <100000000>; }; - pcie0_refclk_gated: pcie0-refclk-gated { + pcie0_refclk_gated: pcie0-refclk-gated { compatible = "gpio-gate-clock"; clocks = <&pcie0_refclk>; #clock-cells = <0>; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dts b/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dts index a02b31c42db4..299d81a18c06 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp-edimm2.2.dts @@ -101,7 +101,7 @@ &usdhc2 { cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; bus-width = <4>; - pinctrl-names = "default" ; + pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; vmmc-supply = <®_usdhc2_vmmc>; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp.dtsi index 69558ffefa9a..affcc20b20c7 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp.dtsi @@ -49,7 +49,7 @@ regulator-ramp-delay = <3125>; }; - buck2: BUCK2 { + buck2: BUCK2 { nxp,dvs-run-voltage = <950000>; nxp,dvs-standby-voltage = <850000>; regulator-always-on; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds0-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds0-tm070jvhg33.dtso index 2cf1de8c05b4..9ce0744c88a8 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds0-tm070jvhg33.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds0-tm070jvhg33.dtso @@ -12,7 +12,7 @@ status = "okay"; }; -&panel_lvds0{ +&panel_lvds0 { compatible = "tianma,tm070jvhg33"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds1-tm070jvhg33.dtso b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds1-tm070jvhg33.dtso index cbad0cfab292..24f5f932231f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds1-tm070jvhg33.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpqs-mb-smarc-2-lvds1-tm070jvhg33.dtso @@ -12,7 +12,7 @@ status = "okay"; }; -&panel_lvds1{ +&panel_lvds1 { compatible = "tianma,tm070jvhg33"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts index 0c3f1b20b3d7..a82af92d6085 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts @@ -119,7 +119,7 @@ }; }; - reg_22v4_p: regulator-22v4-p { + reg_22v4_p: regulator-22v4-p { compatible = "regulator-fixed"; regulator-name = "22v4_P"; regulator-min-microvolt = <22400000>; @@ -507,7 +507,7 @@ pinctrl-0 = <&pinctrl_i2c3>; status = "okay"; - magnetometer@1e { + magnetometer@1e { compatible = "st,lsm9ds1-magn"; reg = <0x1e>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi index f5d529c5baf3..ad7c0e7422ca 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi @@ -1025,7 +1025,7 @@ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; - magnetometer: magnetometer@1e { + magnetometer: magnetometer@1e { compatible = "st,lsm9ds1-magn"; reg = <0x1e>; pinctrl-names = "default"; @@ -1060,7 +1060,7 @@ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; }; - accel_gyro: accel-gyro@6a { + accel_gyro: accel-gyro@6a { compatible = "st,lsm9ds1-imu"; reg = <0x6a>; vdd-supply = <®_vdd_sen>; diff --git a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts index 767819cce886..b91509bfc9c0 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts @@ -230,7 +230,7 @@ hdmi-bridge@48 { compatible = "lontium,lt8912b"; - reg = <0x48> ; + reg = <0x48>; reset-gpios = <&max7323 0 GPIO_ACTIVE_LOW>; ports { diff --git a/arch/arm64/boot/dts/freescale/imx8qm-var-som-symphony.dts b/arch/arm64/boot/dts/freescale/imx8qm-var-som-symphony.dts index ec55b86c220d..4528627f58c8 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-var-som-symphony.dts +++ b/arch/arm64/boot/dts/freescale/imx8qm-var-som-symphony.dts @@ -303,7 +303,7 @@ }; }; -&pciea{ +&pciea { phys = <&hsio_phy 0 PHY_TYPE_PCIE 0>; phy-names = "pcie-phy"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi index b11da10c5ae3..a44351133428 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-var-som.dtsi @@ -275,15 +275,15 @@ status = "okay"; }; -&mu_m0{ +&mu_m0 { status = "okay"; }; -&mu1_m0{ +&mu1_m0 { status = "okay"; }; -&mu2_m0{ +&mu2_m0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi index 38fc47024841..54a3e2804dae 100644 --- a/arch/arm64/boot/dts/freescale/imx95.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi @@ -1458,7 +1458,7 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; - dmas = <&edma1 12 0 0>, <&edma1 13 0 FSL_EDMA_RX> ; + dmas = <&edma1 12 0 0>, <&edma1 13 0 FSL_EDMA_RX>; dma-names = "tx", "rx"; status = "disabled"; }; @@ -1472,7 +1472,7 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; - dmas = <&edma1 14 0 0>, <&edma1 15 0 FSL_EDMA_RX> ; + dmas = <&edma1 14 0 0>, <&edma1 15 0 FSL_EDMA_RX>; dma-names = "tx", "rx"; status = "disabled"; }; @@ -1486,7 +1486,7 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI1>, <&scmi_clk IMX95_CLK_BUSAON>; clock-names = "per", "ipg"; - dmas = <&edma1 16 0 FSL_EDMA_RX>, <&edma1 17 0 0> ; + dmas = <&edma1 16 0 FSL_EDMA_RX>, <&edma1 17 0 0>; dma-names = "tx", "rx"; status = "disabled"; }; @@ -1500,7 +1500,7 @@ clocks = <&scmi_clk IMX95_CLK_LPSPI2>, <&scmi_clk IMX95_CLK_BUSAON>; clock-names = "per", "ipg"; - dmas = <&edma1 18 0 FSL_EDMA_RX>, <&edma1 19 0 0> ; + dmas = <&edma1 18 0 FSL_EDMA_RX>, <&edma1 19 0 0>; dma-names = "tx", "rx"; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/freescale/imx952.dtsi b/arch/arm64/boot/dts/freescale/imx952.dtsi index 020de00e8285..887abb1c4784 100644 --- a/arch/arm64/boot/dts/freescale/imx952.dtsi +++ b/arch/arm64/boot/dts/freescale/imx952.dtsi @@ -1164,7 +1164,7 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; - dmas = <&edma1 12 0 0>, <&edma1 13 0 FSL_EDMA_RX> ; + dmas = <&edma1 12 0 0>, <&edma1 13 0 FSL_EDMA_RX>; dma-names = "tx", "rx"; status = "disabled"; }; @@ -1178,7 +1178,7 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; - dmas = <&edma1 14 0 0>, <&edma1 15 0 FSL_EDMA_RX> ; + dmas = <&edma1 14 0 0>, <&edma1 15 0 FSL_EDMA_RX>; dma-names = "tx", "rx"; status = "disabled"; }; @@ -1192,7 +1192,7 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; - dmas = <&edma1 16 0 FSL_EDMA_RX>, <&edma1 17 0 0> ; + dmas = <&edma1 16 0 FSL_EDMA_RX>, <&edma1 17 0 0>; dma-names = "tx", "rx"; status = "disabled"; }; @@ -1206,7 +1206,7 @@ clock-names = "per", "ipg"; #address-cells = <1>; #size-cells = <0>; - dmas = <&edma1 18 0 FSL_EDMA_RX>, <&edma1 19 0 0> ; + dmas = <&edma1 18 0 FSL_EDMA_RX>, <&edma1 19 0 0>; dma-names = "tx", "rx"; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi index 996494e34593..a7e5977bc146 100644 --- a/arch/arm64/boot/dts/freescale/s32g2.dtsi +++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi @@ -14,7 +14,7 @@ #address-cells = <2>; #size-cells = <2>; - reserved-memory { + reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; diff --git a/arch/arm64/boot/dts/freescale/s32g3.dtsi b/arch/arm64/boot/dts/freescale/s32g3.dtsi index 31f7aad00b76..0770af61a2c4 100644 --- a/arch/arm64/boot/dts/freescale/s32g3.dtsi +++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi @@ -153,7 +153,7 @@ interrupts = ; }; - reserved-memory { + reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; -- cgit v1.2.3 From 47580f0648398f837aaa3019ba3b7437ed1dea1b Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Thu, 30 Jul 2026 12:33:28 +0800 Subject: arm64: dts: imx95-15x15-frdm: fix duplicated can-phy node names Both the flexcan2 and flexcan5 CAN transceiver PHY nodes use the same node name "can-phy", which results in a node name collision. Distinguish them by using unit-less unique names "can-phy0" and "can-phy1". These two CAN PHYs share their silent pin, this shared GPIO can be handled by GPIO shared proxy. Signed-off-by: Haibo Chen Fixes: 9bdfeed989b1 ("arm64: dts: freescale: imx95: Add support for i.MX95 15x15 FRDM board") Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts index 0f43e3be7058..7ed9ff978432 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts @@ -56,7 +56,7 @@ num-channels = <2>; }; - flexcan2_phy: can-phy { + flexcan2_phy: can-phy0 { compatible = "nxp,tja1051"; #phy-cells = <0>; max-bitrate = <5000000>; @@ -67,7 +67,7 @@ silent-gpios = <&pcal6524 7 GPIO_ACTIVE_HIGH>; }; - flexcan5_phy: can-phy { + flexcan5_phy: can-phy1 { compatible = "nxp,tja1051"; #phy-cells = <0>; max-bitrate = <5000000>; -- cgit v1.2.3 From cffa94c6fff068e6b16c2cbe5ba36554d103f3fe Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:45 +0200 Subject: arm64: dts: imx8mp: Add DT label to SPBA5 bus Add DT label to SPBA5 bus for usage in board DTs. No functional change. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index 9cf9f6f08654..bec64cbb3634 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -1437,7 +1437,7 @@ #access-controller-cells = <3>; ranges = <0x30c00000 0x30c00000 0x400000>; - spba-bus@30c00000 { + spba5: spba-bus@30c00000 { compatible = "fsl,spba-bus", "simple-bus"; reg = <0x30c00000 0x100000>; #address-cells = <1>; -- cgit v1.2.3 From 9c1214fbc1658ccae46e77073fde450dc97331e2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:46 +0200 Subject: arm64: dts: imx8mm: imx8mp: Add LVDS DTOs for Data Modul i.MX8M Mini and Plus eDM SBC Add DT overlay for the DSI-to-LVDS adapter eDM-MOD-iMX8Mm-LVDS populated with Lontium LT9211 bridge. This adapter can be optionally populated onto the eDM SBC. This adapter can be extended with multiple panels, currently supported are the following: - AUO G215HVN011 - Innolux G070Y2-L01 - Innolux G101ICE-L01 - Innolux G121XCE-L01 - Innolux G156HCE-L01 - Multi-Inno Technology MI0700A2T-30 - Multi-Inno Technology MI1010Z1T-1CP11 Note that in case of the i.MX8M Plus eDM SBC, the adapter name containing iMX8Mm is not a typo, this is the adapter model string. The adapter was originally developed for the iMX8Mm eDM SBC. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 134 ++++++++++++++++++++- ...odul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi | 59 +++++++++ ...edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi | 118 ++++++++++++++++++ ...l-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi | 32 +++++ ...sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi | 12 ++ ...sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso | 7 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi | 12 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso | 7 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi | 12 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso | 7 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi | 12 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso | 7 ++ ...sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi | 12 ++ ...sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso | 7 ++ ...c-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi | 12 ++ ...c-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso | 7 ++ ...verlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi | 12 ++ ...verlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso | 7 ++ ...edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi | 20 +++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi | 22 ++++ ...imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi | 19 +++ ...imx8mm-data-modul-edm-sbc-overlay-lvds-5v0.dtsi | 19 +++ ...mx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi | 29 +++++ ...data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi | 31 +++++ ...ata-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi | 31 +++++ ...ata-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi | 31 +++++ ...ata-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi | 31 +++++ ...data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi | 30 +++++ ...ta-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi | 31 +++++ ...modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi | 31 +++++ ...8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi | 13 ++ .../dts/freescale/imx8mm-data-modul-edm-sbc.dts | 8 +- ...sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso | 7 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso | 7 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso | 7 ++ ...bc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso | 7 ++ ...sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso | 11 ++ ...c-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso | 7 ++ ...verlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso | 7 ++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi | 35 ++++++ ...sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtso | 24 ++++ ...bc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtso | 24 ++++ ...bc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtso | 24 ++++ ...bc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtso | 32 +++++ ...sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtso | 36 ++++++ ...c-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtso | 24 ++++ ...verlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtso | 24 ++++ ...-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi | 79 ++++++++++++ .../dts/freescale/imx8mp-data-modul-edm-sbc.dts | 48 ++++---- 49 files changed, 1191 insertions(+), 34 deletions(-) create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-5v0.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 8e6216b5c83a..47065c85011c 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -119,7 +119,51 @@ dtb-$(CONFIG_ARCH_MXC) += imx8dxl-hummingboard-telematics.dtb dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdp-mba8xx.dtb dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdps-mb-smarc-2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-beacon-kit.dtb -dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtbo + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtbo + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtbo + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtbo + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtbo + +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo + +dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo + dtb-$(CONFIG_ARCH_MXC) += imx8mm-ddr4-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-emcon-avari.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-emtop-baseboard.dtb @@ -280,7 +324,93 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-aristainetos3-proton2s.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-beacon-kit.dtb DTC_FLAGS_imx8mp-cubox-m := -@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-cubox-m.dtb -dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtbo + +dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtbo + dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-model-a.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-som-a-bmb-08.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-dhcom-drc02.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi new file mode 100644 index 000000000000..8a95dc05b1fc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include +#include + +&{/} { + reg_backlight_en_level: regulator-backlight-en-level { + compatible = "regulator-gpio"; + regulator-name = "Backlight_SEL_EN"; + regulator-type = "voltage"; + states = <3300000 0x0>, + <5000000 0x1>; + + /* Default setting: lowest supported voltage. */ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_backlight_pwm_level: regulator-backlight-pwm-level { + compatible = "regulator-gpio"; + regulator-name = "Backlight_SEL_PWM"; + regulator-type = "voltage"; + gpios = <&gpio_display 2 GPIO_ACTIVE_HIGH>; /* SEL_PWM */ + states = <3300000 0x0>, + <5000000 0x1>; + + /* Default setting: lowest supported voltage. */ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + reg_panel_bl: regulator-panel-bl { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_panel_backlight>; + regulator-name = "PANEL_BL"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 0 0>; + enable-active-high; + /* Used by panels which enable PWM signal before BL ON/OFF */ + status = "disabled"; + }; +}; + +®_panel_vcc { + compatible = "regulator-gpio"; + regulator-type = "voltage"; + enable-active-high; + status = "okay"; + + /* Default setting: lowest supported voltage. */ + gpios-states = <0 0>; /* Default GPIO state is LOW/LOW, so 3V3 out */ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi new file mode 100644 index 000000000000..9abd188ee271 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +&{/} { + reg_lt9211_vcc18: regulator-lt9211-vcc18 { + compatible = "regulator-fixed"; + regulator-name = "LT9211_VCC18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&buck5_reg>; /* X400 pin 51, +1V8_S0 */ + }; +}; + +&i2c_display { /* Display connector I2C */ + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + + lt9211_codec: bridge@2d { + compatible = "lontium,lt9211"; + reg = <0x2d>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_panel_expansion>; + interrupts-extended = <&gpio2 3 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; + vccio-supply = <®_lt9211_vcc18>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9211_a: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&mipi_dsi_bridge1_out>; + }; + }; + }; + }; + + gpio_display: io-expander@41 { + compatible = "nxp,pca9536"; + reg = <0x41>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "SEL_12V", "SEL_5V", "SEL_PWM", "SEL_EN"; + }; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +®_backlight_en_level { + gpios = <&gpio_display 3 GPIO_ACTIVE_HIGH>; /* SEL_EN */ +}; + +®_backlight_pwm_level { + gpios = <&gpio_display 2 GPIO_ACTIVE_HIGH>; /* SEL_PWM */ +}; + +®_panel_bl { + gpio = <&gpio3 0 0>; +}; + +&iomuxc { + /* Free &pinctrl_panel_expansion from hog for lt9211_codec above */ + pinctrl-0 = <&pinctrl_hog_misc>, <&pinctrl_hog_feature>, + <&pinctrl_hog_panel>, <&pinctrl_hog_sbc>; +}; + +&mipi_dsi { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + mipi_dsi_bridge1_out: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + /* Clock and data lanes have DN/DP swapped */ + lane-polarities = <1 1 1 1 1>; + remote-endpoint = <<9211_a>; + }; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +®_panel_vcc { + /* + * AP63300 voltage divider settings: + * R1=16k2 + * R2=5k23 with optional series Rs=7k68 (5V) or Rt=1k5 (12V) + * + * 1 / Rx = (1 / R2) [ + (1 / Rs)][ + (1 / Rt)] + * Vout = 0.8 * ((R1 / Rx) + 1) + */ + gpios = <&gpio_display 1 GPIO_ACTIVE_HIGH>, /* 5V */ + <&gpio_display 0 GPIO_ACTIVE_HIGH>; /* 12V */ + states = <3300000 0x0>, + <5000000 0x1>, + <12000000 0x2>, + <3900000 0x3>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi new file mode 100644 index 000000000000..abe50eb8b4b6 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +<9211_codec { + ports { + port@2 { + reg = <2>; + + lt9211_out_a: endpoint { + remote-endpoint = <&panel_lvds_a>; + }; + }; + + port@3 { + reg = <3>; + + lt9211_out_b: endpoint { + remote-endpoint = <&panel_lvds_b>; + }; + }; + }; +}; + +&panel_lvds_a { + remote-endpoint = <<9211_out_a>; +}; + +&panel_lvds_b { + remote-endpoint = <<9211_out_b>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi new file mode 100644 index 000000000000..cca52464a695 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <216000000>; /* RX ByteClock ~27 MHz */ + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso new file mode 100644 index 000000000000..5d1ea31f33de --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi new file mode 100644 index 000000000000..52d216fbba43 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <515000000>; + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso new file mode 100644 index 000000000000..2d1bbdd06522 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi new file mode 100644 index 000000000000..aba3c9a1a3e8 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <470000000>; + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso new file mode 100644 index 000000000000..bc2f6fef6256 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi new file mode 100644 index 000000000000..f478f4e557cc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <864000000>; + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso new file mode 100644 index 000000000000..5bd417cbac55 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi new file mode 100644 index 000000000000..21bec8a01287 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-dual.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <864000000>; /* RX ByteClock ~27 MHz */ + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso new file mode 100644 index 000000000000..75ae12dfd7fc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi new file mode 100644 index 000000000000..38a3a9a4c75b --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <216000000>; /* RX ByteClock ~27 MHz */ + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso new file mode 100644 index 000000000000..ee2c79664e35 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi new file mode 100644 index 000000000000..98b5c5883cfd --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi" + +&mipi_dsi { + samsung,burst-clock-frequency = <400000000>; + samsung,esc-clock-frequency = <10000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso new file mode 100644 index 000000000000..d05f0dcc3137 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi new file mode 100644 index 000000000000..9e70c1481c1e --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-single.dtsi @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +<9211_codec { + ports { + port@2 { + reg = <2>; + + lt9211_out_a: endpoint { + remote-endpoint = <&panel_lvds>; + }; + }; + }; +}; + +&panel_lvds { + remote-endpoint = <<9211_out_a>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi new file mode 100644 index 000000000000..31598aa86b10 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi" + +&lcdif { + status = "okay"; +}; + +<9211_codec { + interrupts-extended = <&gpio2 3 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; +}; + +®_panel_vcc { + enable-gpios = <&gpio3 6 0>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi new file mode 100644 index 000000000000..0955764c0ebf --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +®_backlight_pwm_level { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; + +®_backlight_en_level { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; + +®_panel_vcc { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-5v0.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-5v0.dtsi new file mode 100644 index 000000000000..70ad6bb9b80a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-5v0.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +®_backlight_pwm_level { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +}; + +®_backlight_en_level { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +}; + +®_panel_vcc { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi new file mode 100644 index 000000000000..65f9ad81cfbc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +&panel { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dual-lvds-odd-pixels; + + panel_lvds_b: endpoint { + }; + }; + + port@1 { + reg = <1>; + dual-lvds-even-pixels; + + panel_lvds_a: endpoint { + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi new file mode 100644 index 000000000000..80f7b74f1ea0 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi" + +&backlight { + power-supply = <®_panel_bl>; + /* 6.3 POWER ON/OFF SEQUENCE, T9 >= 10 ms */ + pwm-off-delay-ms = <10>; + /* 3.2 BACKLIGHT UNIT fPWM=200 Hz (Typ.), value below in ns */ + pwms = <&pwm1 0 5000000 0>; + status = "okay"; +}; + +&panel { + compatible = "innolux,g070y2-l01"; +}; + +®_panel_bl { + startup-delay-us = <10000>; /* T8 */ + off-on-delay-us = <550000>; /* T9 + T6 + T3 + T7 + T4 + T1 + T2 + T5 */ + status = "okay"; +}; + +®_panel_vcc { + /* 6.3 POWER ON/OFF SEQUENCE */ + startup-delay-us = <1000>; /* 0.5ms <= T1 + T2 <= 60 ms */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi new file mode 100644 index 000000000000..1a2bd204c30b --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi" + +&backlight { + power-supply = <®_panel_bl>; + /* 6.3 POWER ON/OFF SEQUENCE, T9 >= 10 ms */ + pwm-off-delay-ms = <10>; + /* 3.2 BACKLIGHT UNIT fPWM=200 Hz (Typ.), value below in ns */ + pwms = <&pwm1 0 5000000 0>; + status = "okay"; +}; + +&panel { + compatible = "innolux,g101ice-l01"; +}; + +®_panel_bl { + startup-delay-us = <10000>; /* T8 */ + off-on-delay-us = <950000>; /* T9 + T6 + T3 + T7 + T4 + T1 + T2 + T5 */ + status = "okay"; +}; + +®_panel_vcc { + /* 6.3 POWER ON/OFF SEQUENCE */ + startup-delay-us = <1000>; /* 0.5ms <= T1 + T2 <= 60 ms */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi new file mode 100644 index 000000000000..f87e8c821dac --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024 Wael Karman + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi" + +&backlight { + power-supply = <®_panel_bl>; + /* 6.2 POWER ON/OFF SEQUENCE, T9 >= 10 ms */ + pwm-off-delay-ms = <10>; + /* 3.2 BACKLIGHT UNIT fPWM=200 Hz (Typ.), value below in ns */ + pwms = <&pwm1 0 5000000 0>; + status = "okay"; +}; + +&panel { + compatible = "innolux,g121xce-l01"; +}; + +®_panel_bl { + startup-delay-us = <10000>; /* T8 */ + off-on-delay-us = <1180000>; /* T9 + T6 + T3 + T7 + T4 + T1 + T2 + T5 */ + status = "okay"; +}; + +®_panel_vcc { + /* 6.2 POWER ON/OFF SEQUENCE */ + startup-delay-us = <1000>; /* 0.5ms <= T1 + T2 <= 60 ms */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi new file mode 100644 index 000000000000..46c8bc7021a4 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi" + +&backlight { + power-supply = <®_panel_bl>; + /* 4.6 POWER ON/OFF SEQUENCE, T9 >= 10 ms */ + pwm-off-delay-ms = <10>; + /* 4.3.2 BACKLIGHT UNIT fPWM=200 Hz (Typ.), value below in ns */ + pwms = <&pwm1 0 5000000 0>; + status = "okay"; +}; + +&panel { + compatible = "innolux,g156hce-l01"; +}; + +®_panel_bl { + startup-delay-us = <10000>; /* T8 */ + off-on-delay-us = <1170000>; /* T9 + T6 + T3 + T7 + T4 + T1 + T2 + T5 */ + status = "okay"; +}; + +®_panel_vcc { + /* 4.6 POWER ON/OFF SEQUENCE */ + startup-delay-us = <1000>; /* 0.5ms <= T1 + T2 <= 60 ms */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi new file mode 100644 index 000000000000..3585170bd59d --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-5v0.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-dual.dtsi" + +&backlight { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_panel_backlight>; + enable-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>; + /* 6.5 POWER ON/OFF SEQUENCE, T6 >= 10 ms */ + post-pwm-on-delay-ms = <10>; + /* 6.5 POWER ON/OFF SEQUENCE, T7 >= 0 ms */ + pwm-off-delay-ms = <10>; + /* 5.2 BACKLIGHT UNIT 200Hz..20kHz, value below in ns */ + pwms = <&pwm1 0 66666 0>; /* 15 kHz = 66666ns */ + status = "okay"; +}; + +&panel { + /* The G215HVN01 is replacement for T215HVN01, which is supported. */ + compatible = "auo,t215hvn01"; +}; + +®_panel_vcc { + /* 6.5 POWER ON/OFF SEQUENCE */ + startup-delay-us = <40000>; /* 30.5ms <= T1 + T2 <= 60 ms */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi new file mode 100644 index 000000000000..4a077e6e6b8a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi" + +&backlight { + power-supply = <®_panel_bl>; + /* 1.5 POWER ON/OFF SEQUENCE, T4 >= 200 ms */ + pwm-off-delay-ms = <200>; + /* ELECTRICAL CHARACTERISTICS, BL_ADJ Frequency 20K HZ Typ., value below in ns */ + pwms = <&pwm1 0 50000 0>; + status = "okay"; +}; + +&panel { + compatible = "multi-inno,mi0700a2t-30"; +}; + +®_panel_bl { + startup-delay-us = <200000>; /* T3 */ + off-on-delay-us = <1450000>; /* T4 + T5 + T6 + T1 + T2 + T3 */ + status = "okay"; +}; + +®_panel_vcc { + /* 1.5 POWER ON/OFF SEQUENCE */ + startup-delay-us = <60000>; /* T1 + T2 >= 1 ms (typ. 60ms) */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi new file mode 100644 index 000000000000..e8d8cd85d04a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-3v3.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi" + +&backlight { + power-supply = <®_panel_bl>; + /* 3 POWER ON/OFF SEQUENCE, T7 >= 200 ms */ + pwm-off-delay-ms = <200>; + /* ELECTRICAL CHARACTERISTICS, BL_ADJ Frequency 20K HZ Typ., value below in ns */ + pwms = <&pwm1 0 50000 0>; + status = "okay"; +}; + +&panel { + compatible = "multi-inno,mi1010z1t-1cp11"; +}; + +®_panel_bl { + startup-delay-us = <200000>; /* T6 */ + off-on-delay-us = <1450000>; /* T7 + T3 + T4 + T5 + T1 + T2 + T6 */ + status = "okay"; +}; + +®_panel_vcc { + /* 3 POWER ON/OFF SEQUENCE */ + startup-delay-us = <60000>; /* T1 + T2 >= 1 ms (typ. 60ms) */ +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi new file mode 100644 index 000000000000..68c20692241a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-lvds-single.dtsi @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +&panel { + status = "okay"; + + port { + panel_lvds: endpoint { + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts index 472c584fb3bd..df857de0375c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts @@ -30,11 +30,8 @@ backlight: backlight { compatible = "pwm-backlight"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_panel_backlight>; brightness-levels = <0 1 10 20 30 40 50 60 70 75 80 90 100>; default-brightness-level = <7>; - enable-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>; pwms = <&pwm1 0 5000000 0>; /* Disabled by default, unless display board plugged in. */ status = "disabled"; @@ -66,7 +63,6 @@ regulator-name = "PANEL_VCC"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio3 6 0>; enable-active-high; /* Disabled by default, unless display board plugged in. */ status = "disabled"; @@ -454,7 +450,7 @@ }; }; -&i2c3 { /* Display connector I2C */ +i2c_display: &i2c3 { /* Display connector I2C */ /* IMX8MM ERRATA e7805 -- I2C is limited to 384 kHz due to SoC bug */ clock-frequency = <320000>; pinctrl-names = "default", "gpio"; @@ -465,7 +461,7 @@ status = "okay"; }; -&i2c4 { /* Feature connector I2C */ +i2c_feature: &i2c4 { /* Feature connector I2C */ /* IMX8MM ERRATA e7805 -- I2C is limited to 384 kHz due to SoC bug */ clock-frequency = <320000>; pinctrl-names = "default", "gpio"; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso new file mode 100644 index 000000000000..6b6b160c0f3a --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso new file mode 100644 index 000000000000..549ea2ab8819 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso new file mode 100644 index 000000000000..c8c432821815 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g121xce-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso new file mode 100644 index 000000000000..bf5b41ae61db --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g156hce-l01.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso new file mode 100644 index 000000000000..faf2c06fc50c --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtso @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g215hvn011.dtsi" + +&backlight { + power-supply = <®_panel_bl_supply>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso new file mode 100644 index 000000000000..359a8b1521b0 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso new file mode 100644 index 000000000000..525cedb64a77 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtso @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi new file mode 100644 index 000000000000..6c346baee903 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds.dtsi @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-common.dtsi" + +&{/} { + reg_panel_bl_supply: regulator-panel-bl-supply { + compatible = "regulator-fixed"; + regulator-name = "BKLT0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; +}; + +&lcdif1 { + status = "okay"; +}; + +<9211_codec { + interrupts-extended = <&gpio4 19 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; +}; + +®_panel_bl { + vin-supply = <®_panel_bl_supply>; +}; + +®_panel_vcc { + enable-gpios = <&gpio3 6 0>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtso new file mode 100644 index 000000000000..7a4126214a4f --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g070y2-l01.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g070y2-l01.dtsi" + +&media_blk_ctrl { + /* + * The G070Y2-L01 panel requires 29.5 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 206.5 MHz , since 206.5 MHz / 7 = 29.5 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <206500000>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds>; +}; + +&panel_lvds { + remote-endpoint = <&ldb_lvds_ch1>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtso new file mode 100644 index 000000000000..817d4ec62d0e --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g101ice-l01.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g101ice-l01.dtsi" + +&media_blk_ctrl { + /* + * The G101ICE-L01 panel requires 71.1 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 497.7 MHz , since 497.7 MHz / 7 = 71.1 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <497700000>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds>; +}; + +&panel_lvds { + remote-endpoint = <&ldb_lvds_ch1>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtso new file mode 100644 index 000000000000..729f477038b1 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g121xce-l01.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024 Wael Karman + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g121xce-l01.dtsi" + +&media_blk_ctrl { + /* + * The G121XCE-L01 panel requires 64.9 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 454.3 MHz , since 454.3 MHz / 7 = 64.9 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <454300000>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds>; +}; + +&panel_lvds { + remote-endpoint = <&ldb_lvds_ch1>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtso new file mode 100644 index 000000000000..86163d6ddd5c --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g156hce-l01.dtso @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g156hce-l01.dtsi" + +&media_blk_ctrl { + /* + * The G156HCE-L01 panel requires 141.86 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 993.2 MHz , since 993.2 MHz / 7 = 141.86 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <993020000>; +}; + +&ldb_lvds_ch0 { + remote-endpoint = <&panel_lvds_b>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds_a>; +}; + +&panel_lvds_a { + remote-endpoint = <&ldb_lvds_ch1>; +}; + +&panel_lvds_b { + remote-endpoint = <&ldb_lvds_ch0>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtso new file mode 100644 index 000000000000..a6d13c360979 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-g215hvn011.dtso @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-g215hvn011.dtsi" + +&backlight { + power-supply = <®_panel_bl_supply>; +}; + +&media_blk_ctrl { + /* + * The G215HVN01 panel requires 148.8 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 1041.6 MHz , since 1041.6 MHz / 7 = 148.8 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <1041600000>; +}; + +&ldb_lvds_ch0 { + remote-endpoint = <&panel_lvds_b>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds_a>; +}; + +&panel_lvds_a { + remote-endpoint = <&ldb_lvds_ch1>; +}; + +&panel_lvds_b { + remote-endpoint = <&ldb_lvds_ch0>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtso new file mode 100644 index 000000000000..76bfbd307ba2 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-mi0700a2t-30.dtsi" + +&media_blk_ctrl { + /* + * The MI0700A2T-30 panel requires 33 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 231 MHz , since 231 MHz / 7 = 33 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <231000000>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds>; +}; + +&panel_lvds { + remote-endpoint = <&ldb_lvds_ch1>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtso new file mode 100644 index 000000000000..4066bac28f3d --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtso @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ + +#include "imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi" +#include "imx8mm-data-modul-edm-sbc-overlay-lvds-mi1010z1t-1cp11.dtsi" + +&media_blk_ctrl { + /* + * The MI1010Z1T-1CP11 panel requires 51.2 MHz LVDS clock. + * Set IMX8MP_VIDEO_PLL1 to 358.4 MHz , since 358.4 MHz / 7 = 51.2 MHz . + */ + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <500000000>, <358400000>; +}; + +&ldb_lvds_ch1 { + remote-endpoint = <&panel_lvds>; +}; + +&panel_lvds { + remote-endpoint = <&ldb_lvds_ch1>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi new file mode 100644 index 000000000000..95f4761869d7 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds.dtsi @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-common.dtsi" + +&{/} { + reg_panel_bl_supply: regulator-panel-bl-supply { + compatible = "regulator-gpio"; + regulator-type = "voltage"; + regulator-name = "PANEL_BL_SUPPLY"; + enable-gpios = <&gpiolvds 0 0>; + enable-active-high; + status = "okay"; + + /* + * MP2328 voltage divider settings: + * R1=51k1 + * R2=5k62 with optional series Rs=2k21 (12V) + * + * 1 / Rx = (1 / R2) [ + (1 / Rs)][ + (1 / Rt)] + * Vout = 0.5 + ((R1 / Rx) * 0.5) + */ + gpios = <&gpiolvds 1 GPIO_ACTIVE_HIGH>; /* 12V */ + states = <5000000 0x0>, + <12000000 0x1>; + + /* Default setting: lowest supported voltage. */ + gpios-states = <1>; /* Default GPIO state is HIGH, so 12V0 out */ + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; +}; + +&lcdif2 { + status = "okay"; +}; + +&lvds_bridge { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +®_backlight_en_level { + gpios = <&gpiolvds 5 GPIO_ACTIVE_HIGH>; /* SEL_EN */ +}; + +®_backlight_pwm_level { + gpios = <&gpiolvds 4 GPIO_ACTIVE_HIGH>; /* SEL_PWM */ +}; + +®_panel_bl { + gpio = <&gpiowifi 0 0>; + vin-supply = <®_panel_bl_supply>; +}; + +®_panel_vcc { + enable-gpios = <&gpiowifi 4 0>; + /* + * MP2328 voltage divider settings: + * R1=51k1 + * R2=9k09 with optional series Rs=14k7 (5V) or Rt=2k94 (12V) + * + * 1 / Rx = (1 / R2) [ + (1 / Rs)][ + (1 / Rt)] + * Vout = 0.5 + ((R1 / Rx) * 0.5) + */ + gpios = <&gpiolvds 2 GPIO_ACTIVE_HIGH>, /* 5V */ + <&gpiolvds 3 GPIO_ACTIVE_HIGH>; /* 12V */ + states = <3300000 0x0>, + <5000000 0x1>, + <12000000 0x2>, + <14000000 0x3>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts index cb28cf1cdd23..c284edfa1f4c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts @@ -30,11 +30,8 @@ backlight: backlight { compatible = "pwm-backlight"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_panel_backlight>; brightness-levels = <0 1 10 20 30 40 50 60 70 75 80 90 100>; default-brightness-level = <7>; - enable-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>; pwms = <&pwm1 0 5000000 0>; /* Disabled by default, unless display board plugged in. */ status = "disabled"; @@ -86,9 +83,6 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-name = "PANEL_VCC"; - /* GPIO flags are ignored, enable-active-high applies. */ - gpio = <&gpio3 6 GPIO_ACTIVE_HIGH>; - enable-active-high; /* Disabled by default, unless display board plugged in. */ status = "disabled"; }; @@ -116,7 +110,7 @@ enable-active-high; off-on-delay-us = <12000>; startup-delay-us = <100>; - vin-supply = <&buck4>; + vin-supply = <&buck4_reg>; }; sound { @@ -152,19 +146,19 @@ }; &A53_0 { - cpu-supply = <&buck2>; + cpu-supply = <&buck2_reg>; }; &A53_1 { - cpu-supply = <&buck2>; + cpu-supply = <&buck2_reg>; }; &A53_2 { - cpu-supply = <&buck2>; + cpu-supply = <&buck2_reg>; }; &A53_3 { - cpu-supply = <&buck2>; + cpu-supply = <&buck2_reg>; }; &ecspi1 { @@ -405,8 +399,8 @@ reg = <0x0a>; #sound-dai-cells = <0>; clocks = <&clk_pwm4>; - VDDA-supply = <&buck4>; - VDDIO-supply = <&buck4>; + VDDA-supply = <&buck4_reg>; + VDDIO-supply = <&buck4_reg>; }; usb-hub@2c { @@ -454,7 +448,9 @@ }; }; -&i2c2 { +i2c_display: &i2c2 { }; + +i2c_feature: &i2c2 { clock-frequency = <100000>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; @@ -527,7 +523,7 @@ * MIMX8ML8CVNKZAB */ regulators { - buck1: BUCK1 { /* VDD_SOC (dual-phase with BUCK3) */ + buck1_reg: BUCK1 { /* VDD_SOC (dual-phase with BUCK3) */ regulator-min-microvolt = <850000>; regulator-max-microvolt = <1000000>; regulator-ramp-delay = <3125>; @@ -535,7 +531,7 @@ regulator-boot-on; }; - buck2: BUCK2 { /* VDD_ARM */ + buck2_reg: BUCK2 { /* VDD_ARM */ nxp,dvs-run-voltage = <950000>; nxp,dvs-standby-voltage = <850000>; regulator-min-microvolt = <850000>; @@ -545,47 +541,47 @@ regulator-boot-on; }; - buck4: BUCK4 { /* VDD_3V3 */ + buck4_reg: BUCK4 { /* VDD_3V3 */ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; }; - buck5: BUCK5 { /* VDD_1V8 */ + buck5_reg: BUCK5 { /* VDD_1V8 */ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; }; - buck6: BUCK6 { /* NVCC_DRAM_1V1 */ + buck6_reg: BUCK6 { /* NVCC_DRAM_1V1 */ regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; regulator-always-on; regulator-boot-on; }; - ldo1: LDO1 { /* NVCC_SNVS_1V8 */ + ldo1_reg: LDO1 { /* NVCC_SNVS_1V8 */ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; }; - ldo3: LDO3 { /* VDDA_1V8 */ + ldo3_reg: LDO3 { /* VDDA_1V8 */ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; }; - ldo4: LDO4 { /* PMIC_LDO4 */ + ldo4_reg: LDO4 { /* PMIC_LDO4 */ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; - ldo5: LDO5 { /* NVCC_SD2 */ + ldo5_reg: LDO5 { /* NVCC_SD2 */ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; }; @@ -650,7 +646,7 @@ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; vmmc-supply = <®_usdhc2_vmmc>; - vqmmc-supply = <&ldo5>; + vqmmc-supply = <&ldo5_reg>; bus-width = <4>; status = "okay"; }; @@ -661,8 +657,8 @@ pinctrl-0 = <&pinctrl_usdhc3>; pinctrl-1 = <&pinctrl_usdhc3_100mhz>; pinctrl-2 = <&pinctrl_usdhc3_200mhz>; - vmmc-supply = <&buck4>; - vqmmc-supply = <&buck5>; + vmmc-supply = <&buck4_reg>; + vqmmc-supply = <&buck5_reg>; bus-width = <8>; no-sd; no-sdio; -- cgit v1.2.3 From 4f55798077dab63ef09d2e1caeb67f836d05d393 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:47 +0200 Subject: arm64: dts: imx8mm: imx8mp: Add legacy board DTOs for Data Modul i.MX8M Mini and Plus eDM SBC Add legacy board revision compatibility DT overlays for both i.MX8M Mini and Plus eDM SBC boards. This adds adjustments to support legacy board revisions. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 38 ++++++++- ...odul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtso | 18 ++++ ...edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtso | 41 +++++++++ ...edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtso | 14 ++++ ...odul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtso | 97 ++++++++++++++++++++++ ...odul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtso | 69 +++++++++++++++ 6 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 47065c85011c..30da4e986aa3 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -148,6 +148,10 @@ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo +imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtbo + dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ @@ -162,7 +166,9 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi0700a2t-30.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtb \ - imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-mi1010z1t-1cp11.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mm-ddr4-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-emcon-avari.dtb @@ -381,6 +387,26 @@ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtbo +DTC_FLAGS_imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01 := -@ + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900-dtbs := \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902-dtbs := \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtbo + +imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtbo + dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ @@ -409,7 +435,15 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi0700a2t-30.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtb \ - imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtbo + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-mi1010z1t-1cp11.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-model-a.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-debix-som-a-bmb-08.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtso new file mode 100644 index 000000000000..14038215f298 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtso @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +&fec1 { + phy-handle = <&fec1_phy_ath>; +}; + +&fec1_phy_ath { + status = "okay"; +}; + +&fec1_phy_bcm { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtso new file mode 100644 index 000000000000..427585b78e45 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev900.dtso @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +&{/} { + reg_panel_vcc_raw: regulator-panel-vcc-raw { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_panel_vcc_reg>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-name = "PANEL_VCC"; + }; +}; + +&panel { + power-supply = <®_panel_vcc_raw>; +}; + +®_backlight_en_level { + status = "disabled"; +}; + +®_backlight_pwm_level { + status = "disabled"; +}; + +®_panel_bl_supply { + status = "disabled"; +}; + +®_panel_bl { + gpio = <&gpio3 0 0>; +}; + +®_panel_vcc { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtso new file mode 100644 index 000000000000..a21fea27e0b4 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-lvds-rev902.dtso @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +®_panel_bl { + gpio = <&gpio3 0 0>; +}; + +®_panel_vcc { + enable-gpios = <&gpio3 6 0>; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtso new file mode 100644 index 000000000000..ec861aa64541 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev900.dtso @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mp-pinfunc.h" + +&eeprom900 { + status = "okay"; +}; + +&eeprom902 { + status = "disabled"; +}; + +&eqos { /* First ethernet */ + phy-handle = <&phy_eqos_ath>; +}; + +&fec { /* Second ethernet */ + /* pinctrl_wifi is ENET2_INT# */ + pinctrl-0 = <&pinctrl_fec &pinctrl_wifi>; + phy-handle = <&phy_fec_ath>; +}; + +&gpiolvds { + status = "disabled"; +}; + +/* + * External pull ups on R242 and R243 on I2C2_SCL_3V3 and I2C2_SDA_3V3 + * are not populated on this early board revision, activate in-SoC pull + * up resistors instead to work around the missing external pull ups. + */ +&pinctrl_i2c2 { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c4 + MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c4 + >; +}; + +&pinctrl_i2c2_gpio { + fsl,pins = < + MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x1c4 + MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x1c4 + >; +}; + +&pcie_phy { + status = "disabled"; +}; + +&pcie { + status = "disabled"; +}; + +&phy_eqos_ath { + /* + * The software support for combination of EEE capable PHY and EEE + * capable MAC is so far missing from the Linux kernel. By default, + * the AR8035 PHY does enable EEE functionality on the PHY side, + * while the EQoS/DWMAC MAC expects to handle the EEE functionality + * on the MAC side. Because the Linux kernel is currently unable to + * align EEE configuration of the PHY and MAC, enabling EEE leads + * to unreliable link. Disable EEE until the kernel support is in + * place. + */ + eee-broken-100tx; + eee-broken-1000t; + status = "okay"; +}; + +&phy_eqos_bcm { + status = "disabled"; +}; + +&phy_fec_ath { + status = "okay"; +}; + +&phy_fec_bcm { + status = "disabled"; +}; + +®_pcie0 { + status = "disabled"; +}; + +&tpm { + status = "disabled"; +}; + +&uart4 { + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtso new file mode 100644 index 000000000000..0141b5d77c6b --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtso @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2024-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mp-pinfunc.h" + +&pinctrl_hog_misc { + fsl,pins = < + /* ENET_WOL# -- shared by both PHYs */ + MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x40000090 + + /* PG_V_IN_VAR# */ + MX8MP_IOMUXC_NAND_CE0_B__GPIO3_IO01 0x40000000 + /* CSI2_PD_1V8 */ + MX8MP_IOMUXC_NAND_DATA02__GPIO3_IO08 0x0 + /* CSI2_RESET_1V8# */ + MX8MP_IOMUXC_NAND_DATA03__GPIO3_IO09 0x0 + + /* DIS_USB_DN1 */ + MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21 0x0 + /* DIS_USB_DN2 */ + MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x0 + + /* EEPROM_WP_1V8# */ + MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x100 + /* PCIE_CLK_GEN_CLKPWRGD_PD_1V8# */ + MX8MP_IOMUXC_SAI5_RXD0__GPIO3_IO21 0x0 + /* GRAPHICS_PRSNT_1V8# */ + MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18 0x40000000 + + /* CLK_CCM_CLKO1_3V3 */ + MX8MP_IOMUXC_GPIO1_IO14__CCM_CLKO1 0x10 + >; +}; + +&pinctrl_pcie0 { + fsl,pins = < + /* M2_PCIE_RST# */ + MX8MP_IOMUXC_GPIO1_IO05__GPIO1_IO05 0x2 + /* M2_W_DISABLE1_1V8# */ + MX8MP_IOMUXC_SAI5_RXD2__GPIO3_IO23 0x2 + /* M2_W_DISABLE2_1V8# */ + MX8MP_IOMUXC_SAI5_RXD3__GPIO3_IO24 0x2 + /* CLK_M2_32K768 */ + MX8MP_IOMUXC_GPIO1_IO00__CCM_EXT_CLK1 0x14 + /* M2_PCIE_WAKE# */ + MX8MP_IOMUXC_GPIO1_IO06__GPIO1_IO06 0x40000140 + /* M2_PCIE_CLKREQ# */ + MX8MP_IOMUXC_I2C4_SCL__PCIE_CLKREQ_B 0x61 + >; +}; + +&pinctrl_uart4 { + fsl,pins = < + MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX 0x49 + MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX 0x49 + >; +}; + +&gpiowifi { + status = "disabled"; +}; + +&uart4 { + status = "disabled"; +}; -- cgit v1.2.3 From 75cd15a15ad3d039998e254f67eac37bb1a25cd6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:48 +0200 Subject: arm64: dts: imx8mm: imx8mp: Add HDMI DTOs for Data Modul i.MX8M Mini and Plus eDM SBC Add DT overlay for the DSI-to-HDMI adapter eDM-MOD-iMX8Mm-HDMI populated with Lontium LT9611 bridge. This adapter can be optionally populated onto the eDM SBC. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 12 +++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi | 94 ++++++++++++++++++++++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso | 17 ++++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso | 17 ++++ 4 files changed, 140 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 30da4e986aa3..bf2674cbc84e 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -120,6 +120,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdp-mba8xx.dtb dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdps-mb-smarc-2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-beacon-kit.dtb +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo @@ -153,6 +157,8 @@ imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900-dtbs := \ imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtb \ @@ -331,6 +337,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-beacon-kit.dtb DTC_FLAGS_imx8mp-cubox-m := -@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-cubox-m.dtb +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo @@ -408,6 +418,8 @@ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902-dtbs := \ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g101ice-l01.dtb \ diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi new file mode 100644 index 000000000000..59f15d5a33a2 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include +#include + +&{/} { + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; +}; + +&i2c_display { /* Display connector I2C */ + #address-cells = <1>; + #size-cells = <0>; + + lt9611_codec: hdmi-bridge@3b { + compatible = "lontium,lt9611"; + reg = <0x3b>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_panel_expansion>; + vcc-supply = <&buck4_reg>; /* X400 pin 55, +3V3_S0 */ + vdd-supply = <&buck5_reg>; /* X400 pin 51, +1V8_S0 */ + + /* Audio I2S not described */ + #sound-dai-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&mipi_dsi_bridge1_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +&iomuxc { + /* Free &pinctrl_panel_expansion from hog for lt9611_codec above */ + pinctrl-0 = <&pinctrl_hog_misc>, <&pinctrl_hog_feature>, + <&pinctrl_hog_panel>, <&pinctrl_hog_sbc>; +}; + +&mipi_dsi { + /* HDMI 148.5 MHz x2 (DDR) x3 (24bpp / 8) */ + samsung,burst-clock-frequency = <891000000>; + samsung,esc-clock-frequency = <10000000>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + mipi_dsi_bridge1_out: endpoint { + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + /* Clock and data lanes have DN/DP swapped */ + lane-polarities = <1 1 1 1 1>; + remote-endpoint = <<9611_a>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso new file mode 100644 index 000000000000..334ba299a354 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi" + +<9611_codec { + interrupts-extended = <&gpio2 3 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; +}; + +&lcdif { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso new file mode 100644 index 000000000000..d8114fd869b5 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtso @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtsi" + +<9611_codec { + interrupts-extended = <&gpio4 19 IRQ_TYPE_EDGE_FALLING>; + reset-gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; +}; + +&lcdif1 { + status = "okay"; +}; -- cgit v1.2.3 From 9a14f327dfcbbb0fa24974cb3a928ea3d7409768 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:49 +0200 Subject: arm64: dts: imx8mm: imx8mp: Add CM DTOs for Data Modul i.MX8M Mini and Plus eDM SBC Add DT overlay which adds CM4/CM7 extras so that CM4/CM7 firmware could be used with remoteproc and rpmsg, but without imposing the overhead on every user of the platform. The CM4 variant applies to i.MX8M Mini, while the CM7 variant applies to i.MX8M Plus . Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 12 +++++ .../imx8mm-data-modul-edm-sbc-overlay-cm4.dtso | 56 +++++++++++++++++++++ .../imx8mp-data-modul-edm-sbc-overlay-cm7.dtso | 57 ++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-cm4.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-cm7.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index bf2674cbc84e..b710cfbf0530 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -120,6 +120,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdp-mba8xx.dtb dtb-$(CONFIG_ARCH_MXC) += imx8dxp-tqma8xdps-mb-smarc-2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mm-beacon-kit.dtb +imx8mm-data-modul-edm-sbc-overlay-cm4-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-cm4.dtbo + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo @@ -157,6 +161,8 @@ imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900-dtbs := \ imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-cm4.dtb \ + imx8mm-data-modul-edm-sbc-overlay-cm4.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ @@ -337,6 +343,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-beacon-kit.dtb DTC_FLAGS_imx8mp-cubox-m := -@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-cubox-m.dtb +imx8mp-data-modul-edm-sbc-overlay-cm7-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-cm7.dtbo + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo @@ -418,6 +428,8 @@ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902-dtbs := \ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-cm7.dtb \ + imx8mp-data-modul-edm-sbc-overlay-cm7.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-cm4.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-cm4.dtso new file mode 100644 index 000000000000..0bd770af2a68 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-cm4.dtso @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include + +&{/} { + #address-cells = <2>; + #size-cells = <2>; + + reserved-memory { /* CM4 reserved memory */ + #address-cells = <2>; + #size-cells = <2>; + ranges; + + m_core_reserved: m_core@b7000000 { + reg = <0 0xb7000000 0 0x1000000>; + no-map; + }; + + vdev0vring0: vdev0vring0@b8000000 { + reg = <0 0xb8000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@b8008000 { + reg = <0 0xb8008000 0 0x8000>; + no-map; + }; + + rsc_table: rsc-table@b80ff000 { + reg = <0 0xb80ff000 0 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@b8400000 { + compatible = "shared-dma-pool"; + reg = <0 0xb8400000 0 0x100000>; + no-map; + }; + }; + + imx8mm-cm4 { + compatible = "fsl,imx8mm-cm4"; + clocks = <&clk IMX8MM_CLK_M4_CORE>; + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu 0 1 + &mu 1 1 + &mu 3 1>; + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; + syscon = <&src>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-cm7.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-cm7.dtso new file mode 100644 index 000000000000..11d342712da6 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-cm7.dtso @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2023-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include + +&{/} { + #address-cells = <2>; + #size-cells = <2>; + + reserved-memory { /* CM7 reserved memory */ + #address-cells = <2>; + #size-cells = <2>; + ranges; + + m_core_reserved: m_core@54000000 { + reg = <0 0x54000000 0 0x1000000>; + no-map; + }; + + vdev0vring0: vdev0vring0@55000000 { + reg = <0 0x55000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@55008000 { + reg = <0 0x55008000 0 0x8000>; + no-map; + }; + + rsc_table: rsc-table@550ff000 { + reg = <0 0x550ff000 0 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@55400000 { + compatible = "shared-dma-pool"; + reg = <0 0x55400000 0 0x100000>; + no-map; + }; + }; + + imx8mp-cm7 { + compatible = "fsl,imx8mp-cm7-mmio"; + clocks = <&clk IMX8MP_CLK_M7_CORE>; + fsl,iomuxc-gpr = <&gpr>; + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu 0 1 + &mu 1 1 + &mu 3 1>; + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; + syscon = <&src>; + }; +}; -- cgit v1.2.3 From af4f12046675a37ceae3dd894e3dbbe590787e4e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:50 +0200 Subject: arm64: dts: imx8mm: imx8mp: Add FIO1 DTOs for Data Modul i.MX8M Mini and Plus eDM SBC Add DT overlay for feature connector expansion module eDM-MOD-iMX8Mm-FIO1 providing additional UARTs, CAN, PWM Beeper, I2C, SPI and GPIO breakout. This adapter can be optionally populated onto the eDM SBC. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 12 ++++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi | 69 ++++++++++++++++++++++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso | 59 ++++++++++++++++++ ...-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso | 46 +++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index b710cfbf0530..81d9e3e33d4b 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -124,6 +124,10 @@ imx8mm-data-modul-edm-sbc-overlay-cm4-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-cm4.dtbo +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo @@ -163,6 +167,8 @@ imx8mm-data-modul-edm-sbc-overlay-edm-sbc-imx8mm-rev900-dtbs := \ dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-cm4.dtb \ imx8mm-data-modul-edm-sbc-overlay-cm4.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ @@ -347,6 +353,10 @@ imx8mp-data-modul-edm-sbc-overlay-cm7-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-cm7.dtbo +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo @@ -430,6 +440,8 @@ imx8mp-data-modul-edm-sbc-overlay-edm-sbc-imx8mp-rev902-dtbs := \ dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-cm7.dtb \ imx8mp-data-modul-edm-sbc-overlay-cm7.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi new file mode 100644 index 000000000000..905db21d57c2 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include +#include + +&{/} { + can_osc: can-osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <20000000>; + }; +}; + +&ecspi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + can_fio: can@0 { + compatible = "microchip,mcp2515"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can>; + clocks = <&can_osc>; + spi-max-frequency = <5000000>; + }; +}; + +&i2c_feature { /* Feature connector I2C */ + #address-cells = <1>; + #size-cells = <0>; + + gpio_feature: io-expander@20 { + compatible = "nxp,pca9554"; + reg = <0x20>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_expander>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio4>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + gpio-line-names = + "GPIO1_output", "GPIO1_input", + "GPIO2_output", "GPIO2_input", + "GPIO3_output", "GPIO3_input", + "PCA9511A_READY", ""; + }; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + pagesize = <32>; + }; +}; + +&uart1 { /* J500/J501 */ + status = "okay"; +}; + +&uart2 { /* RS485 J302/J303 */ + linux,rs485-enabled-at-boot-time; + uart-has-rtscts; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso new file mode 100644 index 000000000000..ad410db5f5b7 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mm-pinfunc.h" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi" + +&{/} { + beeper { + compatible = "pwm-beeper"; + beeper-hz = <1000>; + pwms = <&pwm3 0 250000 0>; + }; +}; + +&can_fio { + interrupts-extended = <&gpio4 25 IRQ_TYPE_LEVEL_LOW>; +}; + +&iomuxc { + pinctrl_can: can-feature-grp { + fsl,pins = < + /* CAN_INT# */ + MX8MM_IOMUXC_SAI2_TXC_GPIO4_IO25 0x400000d6 + /* CAN_RST# */ + MX8MM_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x6 + >; + }; + + pinctrl_gpio_expander: gpio-expander-feature-grp { + fsl,pins = < + /* GPIO4_IO27 */ + MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x6 + >; + }; + + pinctrl_pwm3: pwm3-buzzer-feature-grp { + fsl,pins = < + /* Buzzer PWM output */ + MX8MM_IOMUXC_SPDIF_TX_PWM3_OUT 0x100 + >; + }; +}; + +&pinctrl_hog_feature { + fsl,pins = < + /* GPIO5_IO04 */ + MX8MM_IOMUXC_SPDIF_RX_GPIO5_IO4 0x6 + >; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso new file mode 100644 index 000000000000..0eccb7f7c0a8 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtso @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include "imx8mp-pinfunc.h" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtsi" + +&can_fio { + interrupts-extended = <&gpio2 10 IRQ_TYPE_LEVEL_LOW>; +}; + +&iomuxc { + pinctrl_can: can-feature-grp { + fsl,pins = < + /* CAN_INT# */ + MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x400000d6 + >; + }; + + pinctrl_gpio_expander: gpio-expander-feature-grp { + fsl,pins = < + /* GPIO4_IO27 */ + MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x6 + >; + }; +}; + +&pinctrl_sai2 { + fsl,pins = < + MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0xd6 + MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0xd6 + MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK 0xd6 + >; +}; + +&pinctrl_hog_feature { + fsl,pins = < + /* GPIO5_IO03 */ + MX8MP_IOMUXC_GPIO1_IO07__GPIO1_IO07 0x40000006 + /* GPIO5_IO04 */ + MX8MP_IOMUXC_GPIO1_IO08__GPIO1_IO08 0x40000006 + >; +}; -- cgit v1.2.3 From 4a2011c3d756f49adc6203d5173c2a165e234fc5 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Aug 2026 18:22:51 +0200 Subject: arm64: dts: imx8mm: imx8mp: Add FIO1-Audio DTOs for Data Modul i.MX8M Mini and Plus eDM SBC Add DT overlay for feature connector expansion module eDM-MOD-iMX8Mm-FIO1-Audio providing additional UARTs, CAN, PWM Beeper, I2C, SPI, GPIO breakout and SGTL5000 codec. This adapter can be optionally populated onto the eDM SBC. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 12 +++ ...-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi | 99 ++++++++++++++++++++++ ...-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso | 79 +++++++++++++++++ ...-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso | 67 +++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 81d9e3e33d4b..4372a8618cdb 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -128,6 +128,10 @@ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo +imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio-dtbs := \ + imx8mm-data-modul-edm-sbc.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtbo + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo @@ -169,6 +173,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-data-modul-edm-sbc.dtb \ imx8mm-data-modul-edm-sbc-overlay-cm4.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtb \ + imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ @@ -357,6 +363,10 @@ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo +imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio-dtbs := \ + imx8mp-data-modul-edm-sbc.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtbo + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi-dtbs := \ imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo @@ -442,6 +452,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-data-modul-edm-sbc.dtb \ imx8mp-data-modul-edm-sbc-overlay-cm7.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1.dtbo \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtb \ + imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtb \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-hdmi.dtbo \ imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-lvds-g070y2-l01.dtb \ diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi new file mode 100644 index 000000000000..8b38b5c228e0 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 Marek Vasut + */ + +#include +#include + +&{/} { + can_osc: can-osc { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <20000000>; + }; + + sound-fio { + compatible = "simple-audio-card"; + simple-audio-card,name = "SGTL5000-FIO1"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&codec_dai_fio>; + simple-audio-card,frame-master = <&codec_dai_fio>; + simple-audio-card,widgets = "Headphone", "Headphone Jack"; + simple-audio-card,routing = "Headphone Jack", "HP_OUT"; + + simple-audio-card,cpu { + sound-dai = <&sai2>; + }; + + codec_dai_fio: simple-audio-card,codec { + sound-dai = <&sgtl5000_fio>; + }; + }; +}; + +&ecspi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + can_fio: can@0 { + compatible = "microchip,mcp2518fd"; + reg = <0>; + clocks = <&can_osc>; + spi-max-frequency = <10000000>; + }; +}; + +&i2c_feature { /* Feature connector I2C */ + #address-cells = <1>; + #size-cells = <0>; + + sgtl5000_fio: codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + clocks = <&sai5clk 1>; + VDDA-supply = <&buck4_reg>; + VDDD-supply = <&buck5_reg>; + VDDIO-supply = <&buck4_reg>; + }; + + gpio_feature: io-expander@20 { + compatible = "nxp,pca9554"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + gpio-line-names = + "GPI0", "GPI1", "GPI2", "GPI3", + "GPO0", "GPO1", "GPO2", "GPO3"; + }; + + eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + pagesize = <32>; + }; +}; + +&sai2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai2>; + assigned-clock-rates = <24576000>; + fsl,sai-asynchronous; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + +&uart2 { /* RS422 J12 */ + linux,rs485-enabled-at-boot-time; + uart-has-rtscts; + status = "okay"; +}; + +/* UART4 is blocked by RDC and used as CM4 console UART */ +&uart4 { /* UART to 1-Wire J5 */ + status = "disabled"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso new file mode 100644 index 000000000000..88fa705ac2b6 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include + +#include "imx8mm-pinfunc.h" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi" + +&can_fio { + interrupts-extended = <&gpio4 25 IRQ_TYPE_LEVEL_LOW>; +}; + +&gpio_feature { + interrupt-parent = <&gpio5>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; +}; + +&iomuxc { + pinctrl_codec_mclk: codec-mclk_feature-grp { + fsl,pins = < + /* GPIO4_IO27 */ + MX8MM_IOMUXC_SAI2_MCLK_SAI5_MCLK 0x2 + >; + }; + + pinctrl_sai2: sai2_feature-grp { + fsl,pins = < + MX8MM_IOMUXC_SAI2_RXC_SAI2_RX_BCLK 0x90 + MX8MM_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0x96 + MX8MM_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0x90 + MX8MM_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0x96 + >; + }; +}; + +&pinctrl_hog_feature { + fsl,pins = < + /* GPIO5_IO03 */ + MX8MM_IOMUXC_SPDIF_TX_GPIO5_IO3 0x40000006 + /* GPIO5_IO04 */ + MX8MM_IOMUXC_SPDIF_RX_GPIO5_IO4 0x40000006 + + /* CAN_INT# */ + MX8MM_IOMUXC_SAI2_TXC_GPIO4_IO25 0x40000090 + >; +}; + +&sai2 { + assigned-clocks = <&clk IMX8MM_CLK_SAI2>; + assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>; + fsl,sai-bit-clock-swap; +}; + +&spba2 { + #address-cells = <1>; + #size-cells = <1>; + + sai5clk: clock-controller@30050000 { /* SAI5 */ + compatible = "fsl,imx8mm-sai-clock", "fsl,imx8mq-sai-clock"; + reg = <0x30050000 0x10000>; + #clock-cells = <1>; + clocks = <&clk IMX8MM_CLK_SAI5_IPG>, + <&clk IMX8MM_CLK_SAI5_ROOT>; + clock-names = "bus", "mclk1"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_codec_mclk>; + assigned-clocks = <&clk IMX8MM_CLK_SAI5>, + <&clk IMX8MM_CLK_CLKOUT1_SEL>, + <&clk IMX8MM_CLK_CLKOUT2_SEL>; + assigned-clock-parents = <&clk IMX8MM_CLK_24M>, + <&clk IMX8MM_CLK_24M>, + <&clk IMX8MM_CLK_24M>; + assigned-clock-rates = <24000000>; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso new file mode 100644 index 000000000000..4e2112355350 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtso @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2024-2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +#include + +#include "imx8mp-pinfunc.h" +#include "imx8mm-data-modul-edm-sbc-overlay-edm-mod-imx8mm-fio1-audio.dtsi" + +&can_fio { + interrupts-extended = <&gpio2 10 IRQ_TYPE_LEVEL_LOW>; +}; + +&gpio_feature { + interrupt-parent = <&gpio1>; + interrupts = <8 IRQ_TYPE_LEVEL_LOW>; +}; + +&iomuxc { + pinctrl_codec_mclk: codec-mclk_feature-grp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_MCLK__AUDIOMIX_SAI5_MCLK 0xd6 + >; + }; + + sai2-grp { + fsl,pins = < + MX8MP_IOMUXC_SAI2_TXFS__AUDIOMIX_SAI2_TX_SYNC 0xd6 + MX8MP_IOMUXC_SAI2_TXD0__AUDIOMIX_SAI2_TX_DATA00 0xd6 + MX8MP_IOMUXC_SAI2_TXC__AUDIOMIX_SAI2_TX_BCLK 0xd6 + MX8MP_IOMUXC_SAI2_RXD0__AUDIOMIX_SAI2_RX_DATA00 0xd6 + >; + }; + + uart1-grp { + fsl,pins = < + MX8MP_IOMUXC_SD1_CLK__UART1_DCE_TX 0x49 + MX8MP_IOMUXC_SD1_CMD__UART1_DCE_RX 0x49 + MX8MP_IOMUXC_SD1_DATA1__UART1_DCE_CTS 0x49 + >; + }; +}; + +&sai2 { + assigned-clocks = <&clk IMX8MP_CLK_SAI2>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL2_OUT>; +}; + +&spba5 { + #address-cells = <1>; + #size-cells = <1>; + + sai5clk: clock-controller@30c50000 { + compatible = "fsl,imx8mp-sai-clock", "fsl,imx8mq-sai-clock"; + reg = <0x30c50000 0x10000>; + #clock-cells = <1>; + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_IPG>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI5_MCLK1>; + clock-names = "bus", "mclk1"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_codec_mclk>; + status = "okay"; + }; +}; -- cgit v1.2.3 From 28fc10c538d80dcc55f44ec882b74751dbaeef9a Mon Sep 17 00:00:00 2001 From: Joy Zou Date: Fri, 31 Jul 2026 18:21:45 +0800 Subject: arm64: dts: imx8mq-evk: add regulator-off-in-suspend for VGEN1/VGEN6 VGEN1 and VGEN6 have no consumers and are not always-on. Mark them as regulator-off-in-suspend to disable them properly during suspend and reduce power consumption. Signed-off-by: Joy Zou Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts index 5ea04703ddd7..fc0303e44433 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts @@ -299,6 +299,9 @@ vgen1_reg: vgen1 { regulator-min-microvolt = <800000>; regulator-max-microvolt = <1550000>; + regulator-state-mem { + regulator-off-in-suspend; + }; }; vgen2_reg: vgen2 { @@ -328,6 +331,9 @@ vgen6_reg: vgen6 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; + regulator-state-mem { + regulator-off-in-suspend; + }; }; }; }; -- cgit v1.2.3 From 95117f04d31abfe13ec72b4b73e284c39eecc680 Mon Sep 17 00:00:00 2001 From: Joseph Guo Date: Mon, 20 Jul 2026 15:28:53 +0900 Subject: dt-bindings: arm: fsl: add i.MX952 FRDM board Add DT compatible string for NXP i.MX952 FRDM board. Signed-off-by: Joseph Guo Acked-by: Rob Herring (Arm) Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 6c356623dade..d200840c291e 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1543,6 +1543,7 @@ properties: items: - enum: - fsl,imx952-evk # i.MX952 EVK Board + - fsl,imx952-frdm # i.MX952 FRDM Board - const: fsl,imx952 - description: PHYTEC i.MX 95 FPSC based Boards -- cgit v1.2.3 From 4725482e4e6c9d7b5adfaecd48230d7d83111ecd Mon Sep 17 00:00:00 2001 From: Joseph Guo Date: Mon, 20 Jul 2026 15:28:54 +0900 Subject: arm64: dts: freescale: add i.MX952 FRDM Board support device tree Add basic device tree support for i.MX952 FRDM Board. The board-common hardware description is placed in imx952-frdm.dtsi so that it can be shared with future i.MX952-based FRDM derivative boards. The following peripherals are enabled: - LPUART1 (console), LPUART5 (BT) - USDHC1, USDHC2, USDHC3, - FlexCAN2, FlexCAN3, - USB1, USB2, - LPI2C2, LPI2C4 - WDOG3 - MICFIL (PDM) - LPSPI3 Signed-off-by: Joseph Guo Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 2 + arch/arm64/boot/dts/freescale/imx952-frdm.dts | 9 + arch/arm64/boot/dts/freescale/imx952-frdm.dtsi | 726 +++++++++++++++++++++++++ 3 files changed, 737 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx952-frdm.dts create mode 100644 arch/arm64/boot/dts/freescale/imx952-frdm.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 4372a8618cdb..01c70beeeba6 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -956,6 +956,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-verdin-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx952-evk.dtb +dtb-$(CONFIG_ARCH_MXC) += imx952-frdm.dtb + imx8mm-kontron-dl-dtbs := imx8mm-kontron-bl.dtb imx8mm-kontron-dl.dtbo imx8mm-kontron-bl-lte-dtbs := imx8mm-kontron-bl.dtb imx8mm-kontron-bl-lte.dtbo diff --git a/arch/arm64/boot/dts/freescale/imx952-frdm.dts b/arch/arm64/boot/dts/freescale/imx952-frdm.dts new file mode 100644 index 000000000000..0b9d74eea376 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx952-frdm.dts @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 NXP + */ + +/dts-v1/; + +#include "imx952.dtsi" +#include "imx952-frdm.dtsi" diff --git a/arch/arm64/boot/dts/freescale/imx952-frdm.dtsi b/arch/arm64/boot/dts/freescale/imx952-frdm.dtsi new file mode 100644 index 000000000000..7785eb1a68fc --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx952-frdm.dtsi @@ -0,0 +1,726 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 NXP + */ + +#include + +#define BRD_SM_CTRL_SD3_WAKE 0x8000U /*!< PCAL6408A-0 */ +#define BRD_SM_CTRL_M2M_WAKE 0x8003U /*!< PCAL6408A-6 */ +#define BRD_SM_CTRL_BUTTON 0x8004U /*!< PCAL6408A-7 */ + +/ { + compatible = "fsl,imx952-frdm", "fsl,imx952"; + model = "NXP i.MX952 FRDM board"; + + aliases { + gpio0 = &gpio1; + gpio1 = &gpio2; + gpio2 = &gpio3; + gpio3 = &gpio4; + gpio4 = &gpio5; + i2c0 = &lpi2c1; + i2c1 = &lpi2c2; + i2c2 = &lpi2c3; + i2c3 = &lpi2c4; + i2c4 = &lpi2c5; + i2c5 = &lpi2c6; + i2c6 = &lpi2c7; + i2c7 = &lpi2c8; + mmc0 = &usdhc1; + mmc1 = &usdhc2; + serial0 = &lpuart1; + serial4 = &lpuart5; + spi2 = &lpspi3; + }; + + bt_sco_codec: audio-codec-bt-sco { + compatible = "linux,bt-sco"; + #sound-dai-cells = <1>; + }; + + chosen { + stdout-path = &lpuart1; + }; + + dmic: dmic { + compatible = "dmic-codec"; + #sound-dai-cells = <0>; + num-channels = <2>; + }; + + flexcan2_phy: can-phy0 { + compatible = "nxp,tja1051"; + #phy-cells = <0>; + max-bitrate = <8000000>; + silent-gpios = <&pcal6416 6 GPIO_ACTIVE_HIGH>; + }; + + flexcan3_phy: can-phy1 { + compatible = "nxp,tja1051"; + #phy-cells = <0>; + max-bitrate = <8000000>; + silent-gpios = <&pcal6416 6 GPIO_ACTIVE_HIGH>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "+V1.8_SW"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "+V3.3_SW"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + }; + + reg_5p0v: regulator-5p0v { + compatible = "regulator-fixed"; + regulator-name = "+V5.0_SW"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + }; + + reg_vref_1v8: regulator-adc-vref { + compatible = "regulator-fixed"; + regulator-name = "vref_1v8"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + }; + + reg_dummy: regulator-dummy { + compatible = "regulator-fixed"; + regulator-name = "dummy"; + }; + + reg_ext_12v: regulator-ext-12v { + compatible = "regulator-fixed"; + regulator-name = "VCCEXT_12V"; + regulator-max-microvolt = <12000000>; + regulator-min-microvolt = <12000000>; + vin-supply = <®_ext_5v>; + }; + + reg_ext_3v3: regulator-ext-3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCCEXT_3V3"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + gpio = <&pcal6416 13 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + reg_ext_5v: regulator-ext-5v { + compatible = "regulator-fixed"; + regulator-name = "VCCEXT_5V"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + gpio = <&pcal6416 12 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + reg_m2_pwr: regulator-m2-pwr { + compatible = "regulator-fixed"; + regulator-name = "M.2-power"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + gpio = <&pcal6416 11 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + compatible = "regulator-fixed"; + regulator-name = "VDD_SD2_3V3"; + off-on-delay-us = <12000>; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + pinctrl-names = "default"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usdhc3_vmmc: regulator-usdhc3 { + compatible = "regulator-fixed"; + regulator-name = "WLAN_EN"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + vin-supply = <®_m2_pwr>; + gpio = <&pcal6416 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + /* + * IW612 wifi chip needs more delay than other wifi chips to complete + * the host interface initialization after power up, otherwise the + * internal state of IW612 may be unstable, resulting in the failure of + * the SDIO3.0 switch voltage. + */ + startup-delay-us = <20000>; + }; + + reg_usb_vbus: regulator-vbus { + compatible = "regulator-fixed"; + regulator-name = "USB_VBUS"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + gpio = <&pcal6416 15 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reserved-memory { + ranges; + #address-cells = <2>; + #size-cells = <2>; + + linux_cma: linux,cma { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x80000000 0 0x7f000000>; + reusable; + size = <0 0x3c000000>; + linux,cma-default; + }; + }; + + sound-bt-sco { + compatible = "simple-audio-card"; + simple-audio-card,bitclock-inversion; + simple-audio-card,bitclock-master = <&btcpu>; + simple-audio-card,format = "dsp_a"; + simple-audio-card,frame-master = <&btcpu>; + simple-audio-card,name = "bt-sco-audio"; + + simple-audio-card,codec { + sound-dai = <&bt_sco_codec 1>; + }; + + btcpu: simple-audio-card,cpu { + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + sound-dai = <&sai5>; + }; + }; + + sound-micfil { + compatible = "fsl,imx-audio-card"; + model = "micfil-audio"; + + pri-dai-link { + format = "i2s"; + link-name = "micfil hifi"; + + codec { + sound-dai = <&dmic>; + }; + + cpu { + sound-dai = <&micfil>; + }; + }; + }; + + usdhc3_pwrseq: usdhc3-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&pcal6416 8 GPIO_ACTIVE_LOW>; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0 0x80000000>; + }; +}; + +&adc1 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&asrc1 { + assigned-clocks = <&scmi_clk IMX952_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>, + <&scmi_clk IMX952_CLK_AUDIOPLL2>, + <&scmi_clk IMX952_CLK_ASRC1>; + assigned-clock-parents = <0>, <0>, <0>, <0>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, <3612672000>, + <393216000>, <361267200>, <49152000>; + fsl,asrc-rate = <48000>; + status = "okay"; +}; + +&asrc2 { + assigned-clocks = <&scmi_clk IMX952_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>, + <&scmi_clk IMX952_CLK_AUDIOPLL2>, + <&scmi_clk IMX952_CLK_ASRC2>; + assigned-clock-parents = <0>, <0>, <0>, <0>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, <3612672000>, + <393216000>, <361267200>, <49152000>; + fsl,asrc-rate = <48000>; + status = "okay"; +}; + +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + phys = <&flexcan2_phy>; + status = "okay"; +}; + +&flexcan3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan3>; + phys = <&flexcan3_phy>; + status = "okay"; +}; + +&lpi2c2 { + clock-frequency = <400000>; + pinctrl-0 = <&pinctrl_lpi2c2>; + pinctrl-names = "default"; + status = "okay"; + + pcal6416: gpio@20 { + compatible = "nxp,pcal6416"; + reg = <0x20>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio5>; + interrupts = <14 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + pinctrl-0 = <&pinctrl_pcal6416>; + pinctrl-names = "default"; + vcc-supply = <®_3p3v>; + + /* When low, select CAN; When high, select gpio. */ + can-gpio-sel-hog { + gpios = <4 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-low; + }; + }; +}; + +&lpi2c4 { + clock-frequency = <400000>; + pinctrl-0 = <&pinctrl_lpi2c4>; + pinctrl-names = "default"; + status = "okay"; + + ptn5110: tcpc@50 { + compatible = "nxp,ptn5110", "tcpci"; + reg = <0x50>; + interrupt-parent = <&gpio5>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; + pinctrl-0 = <&pinctrl_ptn5110>; + pinctrl-names = "default"; + + typec_con: connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB-C"; + op-sink-microwatt = <0>; + power-role = "dual"; + self-powered; + sink-pdos = ; + source-pdos = ; + try-power-role = "sink"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + typec1_dr_sw: endpoint { + remote-endpoint = <&usb1_drd_sw>; + }; + }; + }; + }; + }; +}; + +&lpspi3 { + cs-gpios = <&gpio2 8 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pinctrl_lpspi3>; + pinctrl-names = "default"; + status = "okay"; +}; + +&lpuart1 { + /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&lpuart5 { + /* BT */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "okay"; + + bluetooth { + compatible = "nxp,88w8987-bt"; + }; +}; + +&micfil { + assigned-clocks = <&scmi_clk IMX952_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>, + <&scmi_clk IMX952_CLK_AUDIOPLL2>, + <&scmi_clk IMX952_CLK_PDM>; + assigned-clock-parents = <0>, <0>, <0>, <0>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, <3612672000>, + <393216000>, <361267200>, <49152000>; + pinctrl-0 = <&pinctrl_pdm>; + pinctrl-1 = <&pinctrl_pdm_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; + +&sai5 { + assigned-clocks = <&scmi_clk IMX952_CLK_AUDIOPLL1_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL2_VCO>, + <&scmi_clk IMX952_CLK_AUDIOPLL1>, + <&scmi_clk IMX952_CLK_AUDIOPLL2>, + <&scmi_clk IMX952_CLK_SAI5>; + assigned-clock-parents = <0>, <0>, <0>, <0>, <&scmi_clk IMX952_CLK_AUDIOPLL1>; + assigned-clock-rates = <3932160000>, <3612672000>, <393216000>, <361267200>, <12288000>; + #sound-dai-cells = <0>; + pinctrl-0 = <&pinctrl_sai5>; + pinctrl-names = "default"; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + +&scmi_iomuxc { + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + IMX952_PAD_GPIO_IO25__WAKEUPMIX_TOP_CAN2_TX 0x39e + IMX952_PAD_GPIO_IO27__WAKEUPMIX_TOP_CAN2_RX 0x39e + >; + }; + + pinctrl_flexcan3: flexcan3grp { + fsl,pins = < + IMX952_PAD_CCM_CLKO3__WAKEUPMIX_TOP_CAN3_TX 0x39e + IMX952_PAD_CCM_CLKO4__WAKEUPMIX_TOP_CAN3_RX 0x39e + >; + }; + + pinctrl_lpi2c2: lpi2c2grp { + fsl,pins = < + IMX952_PAD_I2C2_SCL__AONMIX_TOP_LPI2C2_SCL 0x40000b9e + IMX952_PAD_I2C2_SDA__AONMIX_TOP_LPI2C2_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c4: lpi2c4grp { + fsl,pins = < + IMX952_PAD_GPIO_IO30__WAKEUPMIX_TOP_LPI2C4_SDA 0x40000b9e + IMX952_PAD_GPIO_IO31__WAKEUPMIX_TOP_LPI2C4_SCL 0x40000b9e + >; + }; + + pinctrl_lpspi3: lpspi3grp { + fsl,pins = < + IMX952_PAD_GPIO_IO08__WAKEUPMIX_TOP_GPIO2_IO_8 0x39e + IMX952_PAD_GPIO_IO09__WAKEUPMIX_TOP_LPSPI3_SIN 0x39e + IMX952_PAD_GPIO_IO10__WAKEUPMIX_TOP_LPSPI3_SOUT 0x39e + IMX952_PAD_GPIO_IO11__WAKEUPMIX_TOP_LPSPI3_SCK 0x39e + >; + }; + + pinctrl_pcal6416: pcal6416grp { + fsl,pins = < + IMX952_PAD_GPIO_IO34__WAKEUPMIX_TOP_GPIO5_IO_14 0x31e + >; + }; + + pinctrl_pdm: pdmgrp { + fsl,pins = < + IMX952_PAD_PDM_CLK__AONMIX_TOP_PDM_CLK 0x31e + IMX952_PAD_PDM_BIT_STREAM0__AONMIX_TOP_PDM_BIT_STREAM_0 0x31e + >; + }; + + pinctrl_pdm_sleep: pdmsleepgrp { + fsl,pins = < + IMX952_PAD_PDM_CLK__AONMIX_TOP_GPIO1_IO_8 0x31e + IMX952_PAD_PDM_BIT_STREAM0__AONMIX_TOP_GPIO1_IO_9 0x31e + >; + }; + + pinctrl_ptn5110: ptn5110grp { + fsl,pins = < + IMX952_PAD_XSPI1_DATA2__WAKEUPMIX_TOP_GPIO5_IO_2 0x31e + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { + fsl,pins = < + IMX952_PAD_SD2_RESET_B__WAKEUPMIX_TOP_GPIO3_IO_7 0x31e + >; + }; + + pinctrl_sai5: sai5grp { + fsl,pins = < + IMX952_PAD_XSPI1_DATA4__WAKEUPMIX_TOP_SAI5_TX_DATA_0 0x31e + IMX952_PAD_XSPI1_DATA5__WAKEUPMIX_TOP_SAI5_TX_SYNC 0x31e + IMX952_PAD_XSPI1_DATA6__WAKEUPMIX_TOP_SAI5_TX_BCLK 0x31e + IMX952_PAD_XSPI1_DATA7__WAKEUPMIX_TOP_SAI5_RX_DATA_0 0x31e + >; + }; + + pinctrl_tpm3: tpm3grp { + fsl,pins = < + IMX952_PAD_GPIO_IO04__WAKEUPMIX_TOP_TPM3_CH0 0x51e + IMX952_PAD_GPIO_IO12__WAKEUPMIX_TOP_TPM3_CH2 0x51e + >; + }; + + pinctrl_tpm4: tpm4grp { + fsl,pins = < + IMX952_PAD_GPIO_IO13__WAKEUPMIX_TOP_TPM4_CH2 0x51e + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + IMX952_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX 0x31e + IMX952_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX 0x31e + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + IMX952_PAD_DAP_TDO_TRACESWO__WAKEUPMIX_TOP_LPUART5_TX 0x31e + IMX952_PAD_DAP_TDI__WAKEUPMIX_TOP_LPUART5_RX 0x31e + IMX952_PAD_DAP_TMS_SWDIO__WAKEUPMIX_TOP_LPUART5_RTS_B 0x31e + IMX952_PAD_DAP_TCLK_SWCLK__WAKEUPMIX_TOP_LPUART5_CTS_B 0x31e + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + IMX952_PAD_SD1_CLK__WAKEUPMIX_TOP_USDHC1_CLK 0x158e + IMX952_PAD_SD1_CMD__WAKEUPMIX_TOP_USDHC1_CMD 0x138e + IMX952_PAD_SD1_DATA0__WAKEUPMIX_TOP_USDHC1_DATA0 0x138e + IMX952_PAD_SD1_DATA1__WAKEUPMIX_TOP_USDHC1_DATA1 0x138e + IMX952_PAD_SD1_DATA2__WAKEUPMIX_TOP_USDHC1_DATA2 0x138e + IMX952_PAD_SD1_DATA3__WAKEUPMIX_TOP_USDHC1_DATA3 0x138e + IMX952_PAD_SD1_DATA4__WAKEUPMIX_TOP_USDHC1_DATA4 0x138e + IMX952_PAD_SD1_DATA5__WAKEUPMIX_TOP_USDHC1_DATA5 0x138e + IMX952_PAD_SD1_DATA6__WAKEUPMIX_TOP_USDHC1_DATA6 0x138e + IMX952_PAD_SD1_DATA7__WAKEUPMIX_TOP_USDHC1_DATA7 0x138e + IMX952_PAD_SD1_STROBE__WAKEUPMIX_TOP_USDHC1_STROBE 0x158e + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { + fsl,pins = < + IMX952_PAD_SD1_CLK__WAKEUPMIX_TOP_USDHC1_CLK 0x158e + IMX952_PAD_SD1_CMD__WAKEUPMIX_TOP_USDHC1_CMD 0x138e + IMX952_PAD_SD1_DATA0__WAKEUPMIX_TOP_USDHC1_DATA0 0x138e + IMX952_PAD_SD1_DATA1__WAKEUPMIX_TOP_USDHC1_DATA1 0x138e + IMX952_PAD_SD1_DATA2__WAKEUPMIX_TOP_USDHC1_DATA2 0x138e + IMX952_PAD_SD1_DATA3__WAKEUPMIX_TOP_USDHC1_DATA3 0x138e + IMX952_PAD_SD1_DATA4__WAKEUPMIX_TOP_USDHC1_DATA4 0x138e + IMX952_PAD_SD1_DATA5__WAKEUPMIX_TOP_USDHC1_DATA5 0x138e + IMX952_PAD_SD1_DATA6__WAKEUPMIX_TOP_USDHC1_DATA6 0x138e + IMX952_PAD_SD1_DATA7__WAKEUPMIX_TOP_USDHC1_DATA7 0x138e + IMX952_PAD_SD1_STROBE__WAKEUPMIX_TOP_USDHC1_STROBE 0x158e + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { + fsl,pins = < + IMX952_PAD_SD1_CLK__WAKEUPMIX_TOP_USDHC1_CLK 0x159e + IMX952_PAD_SD1_CMD__WAKEUPMIX_TOP_USDHC1_CMD 0x139e + IMX952_PAD_SD1_DATA0__WAKEUPMIX_TOP_USDHC1_DATA0 0x139e + IMX952_PAD_SD1_DATA1__WAKEUPMIX_TOP_USDHC1_DATA1 0x139e + IMX952_PAD_SD1_DATA2__WAKEUPMIX_TOP_USDHC1_DATA2 0x139e + IMX952_PAD_SD1_DATA3__WAKEUPMIX_TOP_USDHC1_DATA3 0x139e + IMX952_PAD_SD1_DATA4__WAKEUPMIX_TOP_USDHC1_DATA4 0x139e + IMX952_PAD_SD1_DATA5__WAKEUPMIX_TOP_USDHC1_DATA5 0x139e + IMX952_PAD_SD1_DATA6__WAKEUPMIX_TOP_USDHC1_DATA6 0x139e + IMX952_PAD_SD1_DATA7__WAKEUPMIX_TOP_USDHC1_DATA7 0x139e + IMX952_PAD_SD1_STROBE__WAKEUPMIX_TOP_USDHC1_STROBE 0x159e + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + IMX952_PAD_SD2_CD_B__WAKEUPMIX_TOP_GPIO3_IO_0 0x31e + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + IMX952_PAD_SD2_CLK__WAKEUPMIX_TOP_USDHC2_CLK 0x158e + IMX952_PAD_SD2_CMD__WAKEUPMIX_TOP_USDHC2_CMD 0x138e + IMX952_PAD_SD2_DATA0__WAKEUPMIX_TOP_USDHC2_DATA0 0x138e + IMX952_PAD_SD2_DATA1__WAKEUPMIX_TOP_USDHC2_DATA1 0x138e + IMX952_PAD_SD2_DATA2__WAKEUPMIX_TOP_USDHC2_DATA2 0x138e + IMX952_PAD_SD2_DATA3__WAKEUPMIX_TOP_USDHC2_DATA3 0x138e + IMX952_PAD_SD2_VSELECT__WAKEUPMIX_TOP_USDHC2_VSELECT 0x51e + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + IMX952_PAD_SD2_CLK__WAKEUPMIX_TOP_USDHC2_CLK 0x158e + IMX952_PAD_SD2_CMD__WAKEUPMIX_TOP_USDHC2_CMD 0x138e + IMX952_PAD_SD2_DATA0__WAKEUPMIX_TOP_USDHC2_DATA0 0x138e + IMX952_PAD_SD2_DATA1__WAKEUPMIX_TOP_USDHC2_DATA1 0x138e + IMX952_PAD_SD2_DATA2__WAKEUPMIX_TOP_USDHC2_DATA2 0x138e + IMX952_PAD_SD2_DATA3__WAKEUPMIX_TOP_USDHC2_DATA3 0x138e + IMX952_PAD_SD2_VSELECT__WAKEUPMIX_TOP_USDHC2_VSELECT 0x51e + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + IMX952_PAD_SD2_CLK__WAKEUPMIX_TOP_USDHC2_CLK 0x158e + IMX952_PAD_SD2_CMD__WAKEUPMIX_TOP_USDHC2_CMD 0x138e + IMX952_PAD_SD2_DATA0__WAKEUPMIX_TOP_USDHC2_DATA0 0x138e + IMX952_PAD_SD2_DATA1__WAKEUPMIX_TOP_USDHC2_DATA1 0x138e + IMX952_PAD_SD2_DATA2__WAKEUPMIX_TOP_USDHC2_DATA2 0x138e + IMX952_PAD_SD2_DATA3__WAKEUPMIX_TOP_USDHC2_DATA3 0x138e + IMX952_PAD_SD2_VSELECT__WAKEUPMIX_TOP_USDHC2_VSELECT 0x51e + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + IMX952_PAD_SD3_CLK__WAKEUPMIX_TOP_USDHC3_CLK 0x158e + IMX952_PAD_SD3_CMD__WAKEUPMIX_TOP_USDHC3_CMD 0x138e + IMX952_PAD_SD3_DATA0__WAKEUPMIX_TOP_USDHC3_DATA0 0x138e + IMX952_PAD_SD3_DATA1__WAKEUPMIX_TOP_USDHC3_DATA1 0x138e + IMX952_PAD_SD3_DATA2__WAKEUPMIX_TOP_USDHC3_DATA2 0x138e + IMX952_PAD_SD3_DATA3__WAKEUPMIX_TOP_USDHC3_DATA3 0x138e + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp { + fsl,pins = < + IMX952_PAD_SD3_CLK__WAKEUPMIX_TOP_USDHC3_CLK 0x158e + IMX952_PAD_SD3_CMD__WAKEUPMIX_TOP_USDHC3_CMD 0x138e + IMX952_PAD_SD3_DATA0__WAKEUPMIX_TOP_USDHC3_DATA0 0x138e + IMX952_PAD_SD3_DATA1__WAKEUPMIX_TOP_USDHC3_DATA1 0x138e + IMX952_PAD_SD3_DATA2__WAKEUPMIX_TOP_USDHC3_DATA2 0x138e + IMX952_PAD_SD3_DATA3__WAKEUPMIX_TOP_USDHC3_DATA3 0x138e + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp { + fsl,pins = < + IMX952_PAD_SD3_CLK__WAKEUPMIX_TOP_USDHC3_CLK 0x158e + IMX952_PAD_SD3_CMD__WAKEUPMIX_TOP_USDHC3_CMD 0x138e + IMX952_PAD_SD3_DATA0__WAKEUPMIX_TOP_USDHC3_DATA0 0x138e + IMX952_PAD_SD3_DATA1__WAKEUPMIX_TOP_USDHC3_DATA1 0x138e + IMX952_PAD_SD3_DATA2__WAKEUPMIX_TOP_USDHC3_DATA2 0x138e + IMX952_PAD_SD3_DATA3__WAKEUPMIX_TOP_USDHC3_DATA3 0x138e + >; + }; +}; + +&scmi_misc { + nxp,ctrl-ids = ; +}; + +&tpm3 { + pinctrl-0 = <&pinctrl_tpm3>; + pinctrl-names = "default"; + status = "okay"; +}; + +&tpm4 { + pinctrl-0 = <&pinctrl_tpm4>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usb1 { + adp-disable; + disable-over-current; + dr_mode = "otg"; + hnp-disable; + srp-disable; + usb-role-switch; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; + status = "okay"; + + port { + usb1_drd_sw: endpoint { + remote-endpoint = <&typec1_dr_sw>; + }; + }; +}; + +&usb2 { + disable-over-current; + dr_mode = "host"; + vbus-supply = <®_usb_vbus>; + status = "okay"; +}; + +&usdhc1 { + bus-width = <8>; + non-removable; + no-sd; + no-sdio; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + pinctrl-3 = <&pinctrl_usdhc1>; + pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; + status = "okay"; +}; + +&usdhc2 { + bus-width = <4>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-3 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; + vmmc-supply = <®_usdhc2_vmmc>; + status = "okay"; +}; + +&usdhc3 { + bus-width = <4>; + keep-power-in-suspend; + mmc-pwrseq = <&usdhc3_pwrseq>; + non-removable; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + pinctrl-3 = <&pinctrl_usdhc3>; + pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; + vmmc-supply = <®_usdhc3_vmmc>; + wakeup-source; + status = "okay"; +}; + +&wdog3 { + fsl,ext-reset-output; + status = "okay"; +}; -- cgit v1.2.3 From 70ed8c8923f1b325e7c846e5ed4fee4cc35ecd2e Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Wed, 29 Jul 2026 17:36:27 +0800 Subject: arm64: dts: imx91: Override dpi_bridge's compatible string i.MX91 DPI bridge has a dedicated compatible string "nxp,imx91-pdfc", use it by overriding the original one "nxp,imx93-pdfc" in imx91_93_common.dtsi. Signed-off-by: Liu Ying Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx91.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx91.dtsi b/arch/arm64/boot/dts/freescale/imx91.dtsi index d63569b39bbc..df2532835bb8 100644 --- a/arch/arm64/boot/dts/freescale/imx91.dtsi +++ b/arch/arm64/boot/dts/freescale/imx91.dtsi @@ -62,6 +62,10 @@ compatible = "fsl,imx91-ddr-pmu", "fsl,imx93-ddr-pmu"; }; +&dpi_bridge { + compatible = "nxp,imx91-pdfc"; +}; + &eqos { clocks = <&clk IMX91_CLK_ENET1_QOS_TSN_GATE>, <&clk IMX91_CLK_ENET1_QOS_TSN_GATE>, -- cgit v1.2.3 From f3ed7514ce95aabbccca83042175042c169f9c4e Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Wed, 29 Jul 2026 17:36:28 +0800 Subject: arm64: dts: imx91: Assign media_{axi,apb}_root clock parents/rates According to i.MX91 SoC reference manual, maximal clock frequencies in nominal drive mode for media_axi_root and media_apb_root clocks are 333.33MHz and 125MHz respectively. Assign the clock parents to be IMX93_CLK_SYS_PLL_PFD0 @ 1GHz and IMX93_CLK_SYS_PLL_PFD0_DIV2 @ 500MHz respectively and assign the maximal clock rates by overriding the original settings in imx91_93_common.dtsi. This would effectively achieve media_axi_root clock running at 333.333334MHz and media_apb_root clock running at 125MHz, which aligns to NXP downstream kernel settings. Signed-off-by: Liu Ying Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx91.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx91.dtsi b/arch/arm64/boot/dts/freescale/imx91.dtsi index df2532835bb8..a7355f533d70 100644 --- a/arch/arm64/boot/dts/freescale/imx91.dtsi +++ b/arch/arm64/boot/dts/freescale/imx91.dtsi @@ -120,6 +120,13 @@ <&clk IMX93_CLK_MIPI_CSI_GATE>; clock-names = "apb", "axi", "nic", "disp", "cam", "lcdif", "isi", "csi"; + assigned-clocks = <&clk IMX93_CLK_MEDIA_AXI>, + <&clk IMX93_CLK_MEDIA_APB>, + <&clk IMX93_CLK_MEDIA_DISP_PIX>; + assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD0>, + <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>, + <&clk IMX93_CLK_VIDEO_PLL>; + assigned-clock-rates = <333330000>, <125000000>; }; &ocotp { -- cgit v1.2.3 From 0f90cfe91522125eb89c699fd30cb66a8848cd9f Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Wed, 29 Jul 2026 17:36:29 +0800 Subject: arm64: dts: imx91-9x9-qsb: Add tianma,tm050rdh03 panel Support tianma,tm050rdh03 DPI panel on i.MX91 9x9 QSB. Signed-off-by: Liu Ying Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 4 + .../freescale/imx91-9x9-qsb-tianma-tm050rdh03.dtso | 104 +++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts | 51 ++++++++++ 3 files changed, 159 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx91-9x9-qsb-tianma-tm050rdh03.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 01c70beeeba6..51b217a11fad 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -822,6 +822,10 @@ dtb-$(CONFIG_ARCH_MXC) += imx8qxp-tqma8xqps-mb-smarc-2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8ulp-9x9-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx8ulp-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-9x9-qsb.dtb + +imx91-9x9-qsb-tianma-tm050rdh03-dtbs += imx91-9x9-qsb.dtb imx91-9x9-qsb-tianma-tm050rdh03.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx91-9x9-qsb-tianma-tm050rdh03.dtb + dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-frdm.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-frdm-s.dtb diff --git a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb-tianma-tm050rdh03.dtso b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb-tianma-tm050rdh03.dtso new file mode 100644 index 000000000000..01c22f92e0d8 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb-tianma-tm050rdh03.dtso @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 NXP + */ + +/dts-v1/; +/plugin/; + +#include +#include +#include "imx91-pinfunc.h" + +&{/} { + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&tpm1 3 40000 PWM_POLARITY_INVERTED>; /* 25KHz PWM */ + brightness-levels = <0 100>; + num-interpolated-steps = <100>; + default-brightness-level = <80>; + power-supply = <®_exp_5v>; + }; + + panel { + compatible = "tianma,tm050rdh03"; + backlight = <&backlight>; + enable-gpios = <&pcal6524 8 GPIO_ACTIVE_HIGH>; + power-supply = <®_exp_3v3>; + + port { + panel_in: endpoint { + remote-endpoint = <&dpi_to_panel>; + }; + }; + }; +}; + +&dpi_bridge { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcdif>, <&gpio_fun>, <&sai3_tx_fun>, <&sai3_enable>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + dpi_to_panel: endpoint { + remote-endpoint = <&panel_in>; + bus-width = <18>; + }; + }; + }; +}; + +&iomuxc { + pinctrl_lcdif: lcdifgrp { + fsl,pins = < + MX91_PAD_GPIO_IO00__MEDIAMIX_DISP_CLK 0x31e + MX91_PAD_GPIO_IO01__MEDIAMIX_DISP_DE 0x31e + MX91_PAD_GPIO_IO02__MEDIAMIX_DISP_VSYNC 0x31e + MX91_PAD_GPIO_IO03__MEDIAMIX_DISP_HSYNC 0x31e + MX91_PAD_GPIO_IO04__MEDIAMIX_DISP_DATA0 0x31e + MX91_PAD_GPIO_IO05__MEDIAMIX_DISP_DATA1 0x31e + MX91_PAD_GPIO_IO06__MEDIAMIX_DISP_DATA2 0x31e + MX91_PAD_GPIO_IO07__MEDIAMIX_DISP_DATA3 0x31e + MX91_PAD_GPIO_IO08__MEDIAMIX_DISP_DATA4 0x31e + MX91_PAD_GPIO_IO09__MEDIAMIX_DISP_DATA5 0x31e + MX91_PAD_GPIO_IO10__MEDIAMIX_DISP_DATA6 0x31e + MX91_PAD_GPIO_IO11__MEDIAMIX_DISP_DATA7 0x31e + MX91_PAD_GPIO_IO12__MEDIAMIX_DISP_DATA8 0x31e + MX91_PAD_GPIO_IO13__MEDIAMIX_DISP_DATA9 0x31e + MX91_PAD_GPIO_IO14__MEDIAMIX_DISP_DATA10 0x31e + MX91_PAD_GPIO_IO15__MEDIAMIX_DISP_DATA11 0x31e + MX91_PAD_GPIO_IO16__MEDIAMIX_DISP_DATA12 0x31e + MX91_PAD_GPIO_IO17__MEDIAMIX_DISP_DATA13 0x31e + MX91_PAD_GPIO_IO18__MEDIAMIX_DISP_DATA14 0x31e + MX91_PAD_GPIO_IO19__MEDIAMIX_DISP_DATA15 0x31e + MX91_PAD_GPIO_IO20__MEDIAMIX_DISP_DATA16 0x31e + MX91_PAD_GPIO_IO21__MEDIAMIX_DISP_DATA17 0x31e + >; + }; + + pinctrl_tpm1_ch3: tpm1ch3grp { + fsl,pins = < + MX91_PAD_UART2_TXD__TPM1_CH3 0x31e + >; + }; +}; + +&lcdif { + status = "okay"; +}; + +&media_blk_ctrl { + status = "okay"; +}; + +&tpm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm1_ch3>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts index 044b37fcc0ba..f1ed7983226b 100644 --- a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts +++ b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts @@ -75,6 +75,27 @@ mux-gpios = <&pcal6524 9 GPIO_ACTIVE_HIGH>; }; + exp_mux: mux-controller-3 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6524 22 GPIO_ACTIVE_HIGH>; + }; + + sai3_tx_rx_mux: mux-controller-4 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6524 14 GPIO_ACTIVE_HIGH>; + }; + + sai3_en_mux: mux-controller-5 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6524 23 GPIO_ACTIVE_HIGH>; + }; + pinctrl-gpiomux { compatible = "pinctrl-multiplexer"; @@ -82,6 +103,10 @@ mux-states = <&can_mux 1>; }; + gpio_fun: exp-grp { + mux-states = <&exp_mux 0>; + }; + m2_fun: m2-grp { mux-states = <&sai1_mux 1>; }; @@ -101,6 +126,32 @@ sai1_fun: sai1-grp { mux-states = <&sai1_mux 0>; }; + + sai3_enable: sai3-enable-grp { + mux-states = <&sai3_en_mux 0>; + }; + + sai3_tx_fun: sai3-tx-grp { + mux-states = <&sai3_tx_rx_mux 0>; + }; + }; + + reg_exp_3v3: regulator-exp-3v3 { + compatible = "regulator-fixed"; + regulator-name = "EXP_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6524 21 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_exp_5v: regulator-exp-5v { + compatible = "regulator-fixed"; + regulator-name = "EXP_5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&pcal6524 4 GPIO_ACTIVE_HIGH>; + enable-active-high; }; reg_vref_1v8: regulator-adc-vref { -- cgit v1.2.3 From aadd03cbb635ae153d4f13cdb34931b123d7265e Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Mon, 13 Jul 2026 10:34:35 +0800 Subject: arm64: dts: imx95-19x19-evk: Describe the PCIe M.2 Key E connector The i.MX95-19x19-EVK has the PCIe M.2 Mechanical Key E connector to connect wireless connectivity cards over PCIe and UART interfaces. Hence, describe the connector node and link it with the PCIe 0 Root Port and LPUART5 nodes through graph port/endpoint. Signed-off-by: Sherry Sun Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts | 55 +++++++++++++++++------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts index 814da90243b2..47ed0ef67611 100644 --- a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts @@ -57,6 +57,37 @@ reg = <0x0 0x80000000 0 0x80000000>; }; + m2-connector { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <®_m2_pwr>; + w-disable1-gpios = <&i2c7_pcal6524 6 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcie0_port0_ep>; + }; + }; + + port@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&lpuart5_ep>; + }; + }; + }; + }; + fan0: pwm-fan { compatible = "pwm-fan"; #cooling-cells = <2>; @@ -181,16 +212,6 @@ startup-delay-us = <5000>; }; - reg_pcie0: regulator-pcie { - compatible = "regulator-fixed"; - regulator-name = "PCIE_WLAN_EN"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <®_m2_pwr>; - gpio = <&i2c7_pcal6524 6 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; - reg_slot_pwr: regulator-slot-pwr { compatible = "regulator-fixed"; regulator-name = "PCIe slot-power"; @@ -523,8 +544,10 @@ pinctrl-0 = <&pinctrl_uart5>; status = "okay"; - bluetooth { - compatible = "nxp,88w8987-bt"; + port { + lpuart5_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; }; }; @@ -601,8 +624,12 @@ &pcie0_port0 { reset-gpios = <&i2c7_pcal6524 5 GPIO_ACTIVE_LOW>; - vpcie3v3-supply = <®_pcie0>; - vpcie3v3aux-supply = <®_pcie0>; + + port { + pcie0_port0_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; }; &pcie1 { -- cgit v1.2.3 From 2659fa4fd6f7e3ba63ce3e22fbf49635189b14fa Mon Sep 17 00:00:00 2001 From: Mehmet Fide Date: Mon, 10 Aug 2026 17:22:00 +0200 Subject: ARM: dts: vf500: describe the Cortex-A5 L1 caches The cpu node carries no cache properties, so cacheinfo has nothing to build the hierarchy from and gives up at boot: cacheinfo: Unable to detect cache hierarchy for CPU 0 The level and the type of the two L1 caches come from CLIDR and CCSIDR, but the geometry does not, so /sys/devices/system/cpu/cpu0/cache is left without a size, a line size or a set count. Fill them in from the Vybrid reference manual (NXP VFXXXRM), table 2-4 "Platform modules": the A5 has a 2 way set associative 32 KB instruction cache and a 4 way set associative 32 KB data cache, both with a 32 byte line, so 512 and 256 sets. Tested on a Colibri VF50. The warning is gone and sysfs now reports both caches with the geometry above. Signed-off-by: Mehmet Fide Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/vf/vf500.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/nxp/vf/vf500.dtsi b/arch/arm/boot/dts/nxp/vf/vf500.dtsi index 71ccdaa6f269..a73e9a80e568 100644 --- a/arch/arm/boot/dts/nxp/vf/vf500.dtsi +++ b/arch/arm/boot/dts/nxp/vf/vf500.dtsi @@ -18,6 +18,12 @@ a5_cpu: cpu@0 { compatible = "arm,cortex-a5"; device_type = "cpu"; + d-cache-line-size = <32>; + d-cache-sets = <256>; + d-cache-size = <0x8000>; + i-cache-line-size = <32>; + i-cache-sets = <512>; + i-cache-size = <0x8000>; reg = <0x0>; }; }; -- cgit v1.2.3 From cea697d5f84f94c0cd0d72e4581a6e51538d5b8b Mon Sep 17 00:00:00 2001 From: Mehmet Fide Date: Mon, 10 Aug 2026 17:30:01 +0200 Subject: ARM: dts: vf610: describe the L2 cache geometry The L2 node names the controller and its level, but not its size, line size or set count, so cacheinfo cannot describe the last level of the hierarchy even though the cpu node already points at it. Fill them in from the Vybrid reference manual (NXP VFXXXRM), section 3.2.3: 8 way set associative, 512 KB, 32 byte line, so 2048 sets. Not tested on VF610 silicon, the values come from the manual. The matching change for the L1 caches was tested on a VF500. Signed-off-by: Mehmet Fide Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/vf/vf610.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/nxp/vf/vf610.dtsi b/arch/arm/boot/dts/nxp/vf/vf610.dtsi index 2fba923821d0..ea59e3d6ee49 100644 --- a/arch/arm/boot/dts/nxp/vf/vf610.dtsi +++ b/arch/arm/boot/dts/nxp/vf/vf610.dtsi @@ -14,6 +14,9 @@ reg = <0x40006000 0x1000>; cache-unified; cache-level = <2>; + cache-line-size = <32>; + cache-sets = <2048>; + cache-size = <0x80000>; arm,data-latency = <3 3 3>; arm,tag-latency = <2 2 2>; }; -- cgit v1.2.3 From e12dca0aa2f50034ace8cc47306fbcdb1f82b58e Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Tue, 18 Aug 2026 10:44:57 +0800 Subject: arm64: dts: imx943-evk: Describe the PCIe M.2 Key E connector The i.MX943-EVK has the PCIe M.2 Mechanical Key E connector to connect wireless connectivity cards over PCIe and UART interfaces. Hence, describe the connector node and link it with the PCIe 0 Root Port and LPUART6 nodes through graph port/endpoint. Since currently the M.2 driver doesn't support SD-UART interface, for the supported SD-UART IW612 M.2 module on imx943-evk board, need to add back the WLAN regulator and bluetooth child node. Signed-off-by: Sherry Sun Signed-off-by: Frank Li --- .../boot/dts/freescale/imx943-evk-sdwifi.dtso | 25 ++++++++++ arch/arm64/boot/dts/freescale/imx943-evk.dts | 55 ++++++++++++++++------ 2 files changed, 66 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx943-evk-sdwifi.dtso b/arch/arm64/boot/dts/freescale/imx943-evk-sdwifi.dtso index 59cc1c27b9b9..b95304fd60aa 100644 --- a/arch/arm64/boot/dts/freescale/imx943-evk-sdwifi.dtso +++ b/arch/arm64/boot/dts/freescale/imx943-evk-sdwifi.dtso @@ -6,10 +6,35 @@ /dts-v1/; /plugin/; +#include + +&{/} { + reg_usdhc3_vmmc: regulator-usdhc3 { + compatible = "regulator-fixed"; + regulator-name = "WLAN_EN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_m2_pwr>; + gpio = <&pcal6416_i2c3_u46 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&lpuart6 { + bluetooth { + compatible = "nxp,88w8987-bt"; + }; +}; + +&m2_connector { + status = "disabled"; +}; + &pcie0 { status = "disabled"; }; &usdhc3 { + vmmc-supply = <®_usdhc3_vmmc>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts index 64660f94f4e9..e1f6d64d3a3f 100644 --- a/arch/arm64/boot/dts/freescale/imx943-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts @@ -77,6 +77,37 @@ #sound-dai-cells = <0>; }; + m2_connector: m2-connector { + compatible = "pcie-m2-e-connector"; + vpcie3v3-supply = <®_m2_pwr>; + w-disable1-gpios = <&pcal6416_i2c3_u46 5 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + m2_e_pcie_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&pcie0_port0_ep>; + }; + }; + + port@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + m2_e_uart_ep: endpoint@0 { + reg = <0>; + remote-endpoint = <&lpuart6_ep>; + }; + }; + }; + }; + reg_m2_pwr: regulator-m2-pwr { compatible = "regulator-fixed"; regulator-name = "M.2-power"; @@ -102,16 +133,6 @@ enable-active-high; }; - reg_m2_wlan: regulator-wlan { - compatible = "regulator-fixed"; - regulator-name = "WLAN_EN"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <®_m2_pwr>; - gpio = <&pcal6416_i2c3_u46 5 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; - reg_usdhc2_vmmc: regulator-usdhc2 { compatible = "regulator-fixed"; off-on-delay-us = <12000>; @@ -694,8 +715,10 @@ pinctrl-names = "default"; status = "okay"; - bluetooth { - compatible = "nxp,88w8987-bt"; + port { + lpuart6_ep: endpoint { + remote-endpoint = <&m2_e_uart_ep>; + }; }; }; @@ -1175,7 +1198,12 @@ &pcie0_port0 { reset-gpios = <&pcal6416_i2c3_u46 3 GPIO_ACTIVE_LOW>; - vpcie3v3aux-supply = <®_m2_wlan>; + + port { + pcie0_port0_ep: endpoint { + remote-endpoint = <&m2_e_pcie_ep>; + }; + }; }; &pcie0_ep { @@ -1288,7 +1316,6 @@ pinctrl-1 = <&pinctrl_usdhc3>; pinctrl-names = "default", "sleep"; bus-width = <4>; - vmmc-supply = <®_m2_wlan>; mmc-pwrseq = <&usdhc3_pwrseq>; keep-power-in-suspend; non-removable; -- cgit v1.2.3 From 0a2d2c55750e52ddcde84b80f340b526807e9354 Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Tue, 18 Aug 2026 10:55:44 +0800 Subject: arm64: dts: imx95-15x15-frdm: Move PCIe PERST# and vpcie supply to Root Port node Describing the PCIe PERST# and vpcie supply properties under the Host Bridge node is now deprecated. Add the PERST# (reset-gpios) and the power regulator (vpcie3v3-supply) in the pcie0_port0 Root Port node. Since i.MX95 is the new platform that under development phase, it should be fine to simply move the PERST# and power supply properties. Signed-off-by: Sherry Sun Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts index 7ed9ff978432..54aa8f40f0eb 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts @@ -549,12 +549,15 @@ &pcie0 { pinctrl-0 = <&pinctrl_pcie0>; pinctrl-names = "default"; - reset-gpio = <&gpio5 13 GPIO_ACTIVE_LOW>; supports-clkreq; - vpcie-supply = <®_m2_mkey_pwr>; status = "okay"; }; +&pcie0_port0 { + reset-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + vpcie3v3-supply = <®_m2_mkey_pwr>; +}; + &sai1 { clocks = <&scmi_clk IMX95_CLK_BUSAON>, <&dummy>, <&scmi_clk IMX95_CLK_SAI1>, <&dummy>, -- cgit v1.2.3 From 81b0564d4d442205978946cfaa5788b2edd33a08 Mon Sep 17 00:00:00 2001 From: Joseph Guo Date: Fri, 14 Aug 2026 15:32:38 +0900 Subject: arm64: dts: imx95-15x15-frdm: add boot phase properties Add boot phase properties to essential resources during boot phase. FRDM-IMX95 need UART, SD-Card, eMMC access during boot process. Signed-off-by: Joseph Guo Reviewed-by: Daniel Baluta Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts index 54aa8f40f0eb..947d0c3748c5 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts @@ -140,6 +140,7 @@ regulator-name = "VDD_SD2_3V3"; gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; enable-active-high; + bootph-pre-ram; }; reg_usdhc3_vmmc: regulator-usdhc3 { @@ -445,6 +446,7 @@ &lpuart1 { pinctrl-0 = <&pinctrl_uart1>; pinctrl-names = "default"; + bootph-pre-ram; status = "okay"; }; @@ -724,6 +726,7 @@ fsl,pins = < IMX95_PAD_SD2_RESET_B__GPIO3_IO_BIT7 0x31e >; + bootph-pre-ram; }; pinctrl_uart1: uart1grp { @@ -731,6 +734,7 @@ IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX 0x31e IMX95_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX 0x31e >; + bootph-pre-ram; }; pinctrl_uart5: uart5grp { @@ -756,6 +760,7 @@ IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x138e IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x158e >; + bootph-pre-ram; }; pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { @@ -772,6 +777,7 @@ IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x138e IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x158e >; + bootph-pre-ram; }; pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { @@ -788,12 +794,14 @@ IMX95_PAD_SD1_DATA7__USDHC1_DATA7 0x13fe IMX95_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe >; + bootph-pre-ram; }; pinctrl_usdhc2_gpio: usdhc2gpiogrp { fsl,pins = < IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0 0x31e >; + bootph-pre-ram; }; pinctrl_usdhc2: usdhc2grp { @@ -806,6 +814,7 @@ IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x138e IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e >; + bootph-pre-ram; }; pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { @@ -818,6 +827,7 @@ IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x138e IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e >; + bootph-pre-ram; }; pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { @@ -830,6 +840,7 @@ IMX95_PAD_SD2_DATA3__USDHC2_DATA3 0x138e IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e >; + bootph-pre-ram; }; pinctrl_usdhc3: usdhc3grp { @@ -1004,6 +1015,7 @@ pinctrl-3 = <&pinctrl_usdhc1>; pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; fsl,tuning-step = <1>; + bootph-pre-ram; status = "okay"; }; @@ -1017,6 +1029,7 @@ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; vmmc-supply = <®_usdhc2_vmmc>; fsl,tuning-step = <1>; + bootph-pre-ram; status = "okay"; }; -- cgit v1.2.3 From 1e723caaf0138add254e52654af16466eac09380 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 23 Jul 2026 12:52:17 +0200 Subject: ARM: dts: imx7d-colibri-emmc: Add Toradex Capacitive Touch Display 7" Parallel Add a device tree overlay for the Capacitive Touch Display 7" Parallel on the Colibri iMX7 parallel RGB LCD interface. The panel is a LogicTechno LT161010-2NHC 7" WVGA TFT Transmissive LCD and the touch input is provided by an Atmel MaxTouch capacitive touch controller. The touch controller is connected to the Toradex 10-way Capacitive Touch Interface connector available on Iris v2 and Aster carrier boards. The overlay is also combined with the Iris v2 and Aster carrier board device tree to provide a ready-to-use DTB. Link: https://developer.toradex.com/hardware/accessories/displays/capacitive-touch-display-7inch-parallel/ Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/Makefile | 12 ++++++ ...olibri-emmc-panel-cap-touch-7inch-parallel.dtso | 43 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtso diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile index 1a2539fa19b4..4d2730000202 100644 --- a/arch/arm/boot/dts/nxp/imx/Makefile +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -419,13 +419,25 @@ dtb-$(CONFIG_SOC_IMX6UL) += \ imx6ull-var-som-concerto-full.dtb \ imx6ulz-14x14-evk.dtb \ imx6ulz-bsh-smm-m2.dtb + +imx7d-colibri-emmc-aster-panel-cap-touch-7inch-parallel-dtbs := \ + imx7d-colibri-emmc-aster.dtb \ + imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo + +imx7d-colibri-emmc-iris-v2-panel-cap-touch-7inch-parallel-dtbs := \ + imx7d-colibri-emmc-iris-v2.dtb \ + imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo + dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-colibri-aster.dtb \ imx7d-colibri-emmc-aster.dtb \ + imx7d-colibri-emmc-aster-panel-cap-touch-7inch-parallel.dtb \ imx7d-colibri-emmc-iris.dtb \ imx7d-colibri-emmc-iris-v2.dtb \ + imx7d-colibri-emmc-iris-v2-panel-cap-touch-7inch-parallel.dtb \ imx7d-colibri-emmc-eval-v3.dtb \ + imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo \ imx7d-colibri-eval-v3.dtb \ imx7d-colibri-iris.dtb \ imx7d-colibri-iris-v2.dtb \ diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtso b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtso new file mode 100644 index 000000000000..f336f7b05a2b --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtso @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (c) Toradex + * + * Toradex Capacitive Touch Display 7" Parallel connected through the 40-way + * Unified Interface Display and 10-way Capacitive Touch Interface connectors + * (as featured on Iris v2 and Aster v1.1 carrier boards). + * + * https://docs.toradex.com/104497-7-inch-parallel-capacitive-touch-display-800x480-datasheet.pdf + * https://developer.toradex.com/hardware/accessories/displays/capacitive-touch-display-7inch-parallel/ + * https://www.toradex.com/accessories/capacitive-touch-display-7-inch-parallel + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&atmel_mxt_ts { + pinctrl-0 = <&pinctrl_atmel_connector>; + /* SODIMM 107 / TOUCH_INT# */ + interrupt-parent = <&gpio2>; + interrupts = <15 IRQ_TYPE_EDGE_FALLING>; + /* SODIMM 106 / TOUCH_RST# */ + reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&backlight { + status = "okay"; +}; + +&lcdif { + status = "okay"; +}; + +&panel_dpi { + compatible = "logictechno,lt161010-2nhc"; + + status = "okay"; +}; -- cgit v1.2.3 From 64e7d6ba2037eace0272d21bb32d38081eff74f5 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 23 Jul 2026 12:52:18 +0200 Subject: ARM: dts: imx7d-colibri-emmc: Add Toradex Capacitive Touch Display 7" Parallel with Touch Adapter Add a device tree overlay for the Capacitive Touch Display 7" Parallel on the Colibri iMX7 parallel RGB LCD interface. The panel is a LogicTechno LT161010-2NHC 7" WVGA TFT Transmissive LCD and the touch input is provided by an Atmel MaxTouch capacitive touch controller. The touch controller is connected to the Toradex Capacitive Touch Adapter, the connection to the various carrier boards is documented in the datasheet [1]. The overlay is also combined with the Eval carrier board device tree to provide a ready-to-use DTB. Link: https://developer.toradex.com/hardware/accessories/displays/capacitive-touch-display-7inch-parallel/ Link: https://developer.toradex.com/hardware/accessories/add-ons/capacitive-touch-adapter/ Link: https://docs.toradex.com/104615-capacitive-touch-adapter-datasheet.pdf [1] Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/Makefile | 5 ++ ...nel-cap-touch-7inch-parallel-touch-adapter.dtso | 58 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel-touch-adapter.dtso diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile index 4d2730000202..3c16843c3071 100644 --- a/arch/arm/boot/dts/nxp/imx/Makefile +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -428,6 +428,10 @@ imx7d-colibri-emmc-iris-v2-panel-cap-touch-7inch-parallel-dtbs := \ imx7d-colibri-emmc-iris-v2.dtb \ imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo +imx7d-colibri-emmc-eval-v3-panel-cap-touch-7inch-parallel-touch-adapter-dtbs := \ + imx7d-colibri-emmc-eval-v3.dtb \ + imx7d-colibri-emmc-panel-cap-touch-7inch-parallel-touch-adapter.dtbo + dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-colibri-aster.dtb \ @@ -437,6 +441,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-colibri-emmc-iris-v2.dtb \ imx7d-colibri-emmc-iris-v2-panel-cap-touch-7inch-parallel.dtb \ imx7d-colibri-emmc-eval-v3.dtb \ + imx7d-colibri-emmc-eval-v3-panel-cap-touch-7inch-parallel-touch-adapter.dtb \ imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo \ imx7d-colibri-eval-v3.dtb \ imx7d-colibri-iris.dtb \ diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel-touch-adapter.dtso b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel-touch-adapter.dtso new file mode 100644 index 000000000000..890461f92442 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-cap-touch-7inch-parallel-touch-adapter.dtso @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (c) Toradex + * + * Toradex Capacitive Touch Display 7" Parallel connected through the 40-way + * Unified Interface Display connector and Toradex Capacitive Touch Adapter. + * + * Toradex Capacitive Touch Adapter connection with the various carrier boards + * is documented in the datasheet [1]. + * + * https://developer.toradex.com/hardware/accessories/displays/capacitive-touch-display-7inch-parallel/ + * https://www.toradex.com/accessories/capacitive-touch-display-7-inch-parallel + * https://docs.toradex.com/104497-7-inch-parallel-capacitive-touch-display-800x480-datasheet.pdf + * https://developer.toradex.com/hardware/accessories/add-ons/capacitive-touch-adapter/ + * https://www.toradex.com/accessories/capacitive-touch-adapter + * https://docs.toradex.com/104615-capacitive-touch-adapter-datasheet.pdf [1] + */ + +/dts-v1/; +/plugin/; + +#include +#include + +&atmel_mxt_ts { + pinctrl-0 = <&pinctrl_atmel_adapter>; + /* SODIMM 28 / TOUCH_INT# */ + interrupt-parent = <&gpio1>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + /* SODIMM 30 / TOUCH_RST# */ + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + + status = "okay"; +}; + +&backlight { + status = "okay"; +}; + +&lcdif { + status = "okay"; +}; + +&panel_dpi { + compatible = "logictechno,lt161010-2nhc"; + + status = "okay"; +}; + +/* Conflict with SODIMM 28 / TOUCH_INT# */ +&pwm2 { + status = "disabled"; +}; + +/* Conflict with SODIMM 30 / TOUCH_RST# */ +&pwm3 { + status = "disabled"; +}; -- cgit v1.2.3 From 392bbdb0357b726b116ce3b962c4d8029b8e40b3 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 23 Jul 2026 12:52:19 +0200 Subject: ARM: dts: imx7d-colibri-emmc: Add Toradex Resistive Touch Display 7" Parallel Add a device tree overlay for the Resistive Touch Display 7" Parallel on the Colibri iMX7 parallel RGB LCD interface. The panel is a LogicTechno LT161010-2NHR 7" WVGA TFT Transmissive LCD with a resistive touch. The overlay is also combined with the Eval carrier board device tree to provide a ready-to-use DTB. Link: https://developer.toradex.com/hardware/accessories/displays/resistive-touch-display-7inch-parallel/ Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/Makefile | 5 ++++ ...olibri-emmc-panel-res-touch-7inch-parallel.dtso | 32 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-res-touch-7inch-parallel.dtso diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile index 3c16843c3071..e9f95c3b8353 100644 --- a/arch/arm/boot/dts/nxp/imx/Makefile +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -432,6 +432,10 @@ imx7d-colibri-emmc-eval-v3-panel-cap-touch-7inch-parallel-touch-adapter-dtbs := imx7d-colibri-emmc-eval-v3.dtb \ imx7d-colibri-emmc-panel-cap-touch-7inch-parallel-touch-adapter.dtbo +imx7d-colibri-emmc-eval-v3-panel-res-touch-7inch-parallel-dtbs := \ + imx7d-colibri-emmc-eval-v3.dtb \ + imx7d-colibri-emmc-panel-res-touch-7inch-parallel.dtbo + dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-colibri-aster.dtb \ @@ -442,6 +446,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-colibri-emmc-iris-v2-panel-cap-touch-7inch-parallel.dtb \ imx7d-colibri-emmc-eval-v3.dtb \ imx7d-colibri-emmc-eval-v3-panel-cap-touch-7inch-parallel-touch-adapter.dtb \ + imx7d-colibri-emmc-eval-v3-panel-res-touch-7inch-parallel.dtb \ imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo \ imx7d-colibri-eval-v3.dtb \ imx7d-colibri-iris.dtb \ diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-res-touch-7inch-parallel.dtso b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-res-touch-7inch-parallel.dtso new file mode 100644 index 000000000000..b926cc020e62 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-panel-res-touch-7inch-parallel.dtso @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (c) Toradex + * + * Toradex Resistive Touch Display 7" Parallel connected through the 40-way + * Unified Interface Display connector. + * + * https://docs.toradex.com/104498-7-inch-parallel-resistive-touch-display-800x480.pdf + * https://developer.toradex.com/hardware/accessories/displays/resistive-touch-display-7inch-parallel/ + * https://www.toradex.com/accessories/resistive-touch-display + */ + +/dts-v1/; +/plugin/; + +&ad7879_ts { + status = "okay"; +}; + +&backlight { + status = "okay"; +}; + +&lcdif { + status = "okay"; +}; + +&panel_dpi { + compatible = "logictechno,lt161010-2nhr"; + + status = "okay"; +}; -- cgit v1.2.3 From 94f3c5be8d67d19cf9913c1f5ffbf79a41fdaa3f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 1 Aug 2026 23:04:21 +0200 Subject: ARM: dts: nxp: Correct white-space style Correct a few white-space issues, like missing space before bracket '{' character or spurious space, which will be flagged by dt-check-style ("redundant-whitespace" warning). No functional changes. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Alexander Stein Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/e60k02.dtsi | 8 ++++---- arch/arm/boot/dts/nxp/imx/e70k02.dtsi | 8 ++++---- arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts | 2 +- arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts | 4 ++-- arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts | 8 ++++---- arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts | 8 ++++---- arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts | 2 +- arch/arm/boot/dts/nxp/imx/imx7s-warp.dts | 2 +- arch/arm/boot/dts/nxp/ls/ls1021a.dtsi | 10 +++++----- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/e60k02.dtsi b/arch/arm/boot/dts/nxp/imx/e60k02.dtsi index aac7b9ef7627..ed59b27834a6 100644 --- a/arch/arm/boot/dts/nxp/imx/e60k02.dtsi +++ b/arch/arm/boot/dts/nxp/imx/e60k02.dtsi @@ -240,13 +240,13 @@ }; /* IR_3V3 */ - ldo1_reg: LDO1 { + ldo1_reg: LDO1 { regulator-name = "LDO1"; regulator-boot-on; }; /* Core1_3V3 */ - ldo2_reg: LDO2 { + ldo2_reg: LDO2 { regulator-name = "LDO2"; regulator-always-on; regulator-boot-on; @@ -259,7 +259,7 @@ }; /* Core5_1V2 */ - ldo3_reg: LDO3 { + ldo3_reg: LDO3 { regulator-name = "LDO3"; regulator-always-on; regulator-boot-on; @@ -310,7 +310,7 @@ regulator-boot-on; }; - ldortc1_reg: LDORTC1 { + ldortc1_reg: LDORTC1 { regulator-name = "LDORTC1"; regulator-boot-on; }; diff --git a/arch/arm/boot/dts/nxp/imx/e70k02.dtsi b/arch/arm/boot/dts/nxp/imx/e70k02.dtsi index 3bb11c5a6353..dc7ff108aa85 100644 --- a/arch/arm/boot/dts/nxp/imx/e70k02.dtsi +++ b/arch/arm/boot/dts/nxp/imx/e70k02.dtsi @@ -243,13 +243,13 @@ }; }; - ldo1_reg: LDO1 { + ldo1_reg: LDO1 { regulator-name = "LDO1"; regulator-boot-on; }; /* Core1_3V3 */ - ldo2_reg: LDO2 { + ldo2_reg: LDO2 { regulator-name = "LDO2"; regulator-always-on; regulator-boot-on; @@ -262,7 +262,7 @@ }; /* Core5_1V2 */ - ldo3_reg: LDO3 { + ldo3_reg: LDO3 { regulator-name = "LDO3"; regulator-always-on; regulator-boot-on; @@ -311,7 +311,7 @@ regulator-boot-on; }; - ldortc1_reg: LDORTC1 { + ldortc1_reg: LDORTC1 { regulator-name = "LDORTC1"; regulator-boot-on; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts index ec5a9bf40677..30275319902e 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-mamoj.dts @@ -151,7 +151,7 @@ enable-active-high; }; - reg_wl18xx_vmmc: regulator-wl18xx-vmcc { + reg_wl18xx_vmmc: regulator-wl18xx-vmcc { compatible = "regulator-fixed"; regulator-name = "vwl1807"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts b/arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts index 929def2bb35e..20b6cc74f622 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-bosch-acc.dts @@ -177,7 +177,7 @@ regulator-name = "usb_h2_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - vin-supply = <®_5p0> ; + vin-supply = <®_5p0>; regulator-always-on; }; @@ -207,7 +207,7 @@ regulator-name = "vref_dac"; regulator-min-microvolt = <20000>; regulator-max-microvolt = <20000>; - vin-supply = <®_5p0> ; + vin-supply = <®_5p0>; regulator-boot-on; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts index 657d0f1b6115..47b05207574e 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sl-kobo-aura2.dts @@ -211,14 +211,14 @@ }; /* IR_3V3 */ - ldo1_reg: LDO1 { + ldo1_reg: LDO1 { regulator-name = "LDO1"; regulator-always-on; regulator-boot-on; }; /* Core1_3V3 */ - ldo2_reg: LDO2 { + ldo2_reg: LDO2 { regulator-name = "LDO2"; regulator-always-on; regulator-boot-on; @@ -231,7 +231,7 @@ }; /* Core5_1V2 */ - ldo3_reg: LDO3 { + ldo3_reg: LDO3 { regulator-name = "LDO3"; regulator-always-on; regulator-boot-on; @@ -282,7 +282,7 @@ regulator-boot-on; }; - ldortc1_reg: LDORTC1 { + ldortc1_reg: LDORTC1 { regulator-name = "LDORTC1"; regulator-always-on; regulator-boot-on; diff --git a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts index 4c655579f43e..64a74719c216 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sl-tolino-shine2hd.dts @@ -276,13 +276,13 @@ }; /* IR_3V3 */ - ldo1_reg: LDO1 { + ldo1_reg: LDO1 { regulator-name = "LDO1"; regulator-boot-on; }; /* Core1_3V3 */ - ldo2_reg: LDO2 { + ldo2_reg: LDO2 { regulator-name = "LDO2"; regulator-always-on; regulator-boot-on; @@ -295,7 +295,7 @@ }; /* Core5_1V2 */ - ldo3_reg: LDO3 { + ldo3_reg: LDO3 { regulator-name = "LDO3"; regulator-always-on; regulator-boot-on; @@ -346,7 +346,7 @@ regulator-boot-on; }; - ldortc1_reg: LDORTC1 { + ldortc1_reg: LDORTC1 { regulator-name = "LDORTC1"; regulator-always-on; regulator-boot-on; diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts b/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts index 814401486792..d20d2735cab5 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6sll-evk.dts @@ -633,7 +633,7 @@ >; }; - pinctrl_wdog1: wdog1grp { + pinctrl_wdog1: wdog1grp { fsl,pins = < MX6SLL_PAD_WDOG_B__WDOG1_B 0x170b0 >; diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts index 25f38acc5350..b1989013c1a4 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts @@ -272,7 +272,7 @@ status = "okay"; }; -&uart3 { +&uart3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart3>; assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>; diff --git a/arch/arm/boot/dts/nxp/ls/ls1021a.dtsi b/arch/arm/boot/dts/nxp/ls/ls1021a.dtsi index e0b9ea6dd510..af518fc08809 100644 --- a/arch/arm/boot/dts/nxp/ls/ls1021a.dtsi +++ b/arch/arm/boot/dts/nxp/ls/ls1021a.dtsi @@ -721,7 +721,7 @@ ; }; - queue-group@2d14000 { + queue-group@2d14000 { reg = <0x0 0x2d14000 0x0 0x1000>; interrupts = , , @@ -740,14 +740,14 @@ ranges; dma-coherent; - queue-group@2d50000 { + queue-group@2d50000 { reg = <0x0 0x2d50000 0x0 0x1000>; interrupts = , , ; }; - queue-group@2d54000 { + queue-group@2d54000 { reg = <0x0 0x2d54000 0x0 0x1000>; interrupts = , , @@ -766,14 +766,14 @@ ranges; dma-coherent; - queue-group@2d90000 { + queue-group@2d90000 { reg = <0x0 0x2d90000 0x0 0x1000>; interrupts = , , ; }; - queue-group@2d94000 { + queue-group@2d94000 { reg = <0x0 0x2d94000 0x0 0x1000>; interrupts = , , -- cgit v1.2.3 From 54852806f5b464e0971ab1d00593aabc083418ce Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 23 Jul 2026 15:14:15 -0400 Subject: dt-bindings: display: bridge: ldb: allow a single reg for fsl,imx6sx-ldb The i.MX6SX LDB only provides a single register region for the LDB block, while other supported LDB variants require two register regions. Update the binding schema to allow a single reg entry for fsl,imx6sx-ldb while keeping the existing constraints unchanged for the other compatible strings. Fix below DTB_CHECK warings: arch/arm/boot/dts/nxp/imx/imx6sx-nitrogen6sx.dtb: bridge@18 (fsl,imx6sx-ldb): reg: [[24, 4]] is too short Acked-by: Rob Herring (Arm) Signed-off-by: Frank Li --- .../bindings/display/bridge/fsl,ldb.yaml | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml b/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml index 7f380879fffd..e5a8870bb76a 100644 --- a/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml +++ b/Documentation/devicetree/bindings/display/bridge/fsl,ldb.yaml @@ -28,9 +28,11 @@ properties: const: ldb reg: + minItems: 1 maxItems: 2 reg-names: + minItems: 1 items: - const: ldb - const: lvds @@ -83,15 +85,6 @@ allOf: ports: properties: port@2: false - - if: - not: - properties: - compatible: - contains: - const: fsl,imx6sx-ldb - then: - required: - - reg-names - if: properties: @@ -100,7 +93,19 @@ allOf: const: fsl,imx6sx-ldb then: properties: + reg: + maxItems: 1 + reg-names: + maxItems: 1 nxp,enable-termination-resistor: false + else: + required: + - reg-names + properties: + reg: + minItems: 2 + reg-names: + minItems: 2 additionalProperties: false -- cgit v1.2.3 From 1d9ca906059d106bf2f96cde213dc7382205a82f Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 23 Jul 2026 15:14:16 -0400 Subject: dt-bindings: soc: imx-iomuxc-gpr: allow bridge@18 as child node The legacy i.MX6SX (>15 year) SoC imx-iomuxc-gpr contains one LDB_CTRL register. Allow the LVDS Display Bridge(LDB) child node under imx-iomuxc-gpr. Fix below CHECK_DTBS warnings: arch/arm/boot/dts/nxp/imx/imx6sx-nitrogen6sx.dtb: syscon@20e4000 (fsl,imx6sx-iomuxc-gpr): '#address-cells', '#size-cells', 'bridge@18' do not match any of the regexes: '^ipu[12]_csi[01]_mux$', '^pinctrl-[0-9]+$ Reviewed-by: Rob Herring (Arm) Signed-off-by: Frank Li --- .../bindings/soc/imx/fsl,imx-iomuxc-gpr.yaml | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/imx/fsl,imx-iomuxc-gpr.yaml b/Documentation/devicetree/bindings/soc/imx/fsl,imx-iomuxc-gpr.yaml index 721a67e84c13..49813adce71c 100644 --- a/Documentation/devicetree/bindings/soc/imx/fsl,imx-iomuxc-gpr.yaml +++ b/Documentation/devicetree/bindings/soc/imx/fsl,imx-iomuxc-gpr.yaml @@ -47,10 +47,23 @@ properties: reg: maxItems: 1 + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + + ranges: true + mux-controller: type: object $ref: /schemas/mux/reg-mux.yaml + bridge@18: + type: object + $ref: /schemas/display/bridge/fsl,ldb.yaml# + unevaluatedProperties: false + patternProperties: "^ipu[12]_csi[01]_mux$": type: object @@ -67,6 +80,19 @@ allOf: patternProperties: '^ipu[12]_csi[01]_mux$': false + - if: + properties: + compatible: + not: + contains: + const: fsl,imx6sx-iomuxc-gpr + then: + properties: + bridge@18: false + '#address-cells': false + '#size-cells': false + ranges: false + additionalProperties: false required: @@ -87,4 +113,40 @@ examples: }; }; + - | + #include + + syscon@20e4000 { + compatible = "fsl,imx6sx-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", "syscon", "simple-mfd"; + reg = <0x020e4000 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + bridge@18 { + compatible = "fsl,imx6sx-ldb"; + reg = <0x18 0x4>; + clocks = <&clks IMX6SX_CLK_LDB_DI0>; + clock-names = "ldb"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + endpoint { + }; + }; + + port@1 { + reg = <1>; + + endpoint { + }; + }; + }; + }; + }; ... -- cgit v1.2.3 From a22ad7abfe9c19296a9c1d5a73aba2d405f827f4 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 23 Jul 2026 15:14:17 -0400 Subject: dt-bindings: display: lcdif: Allow display0 child node for i.MX6UL The legacy i.MX6UL LCDIF binding uses a display0 child node to describe the attached display. Update the binding schema to allow this child node for fsl,imx6ul-lcdif. Fixes the following CHECK_DTBS warning: arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-0010.dtb: lcdif@21c8000 (fsl,imx6ul-lcdif): 'disp0' does not match any of the regexes: '^pinctrl-[0-9]+$' A follow-up patch renames the child node from disp0 to display0 to match the updated binding. Acked-by: Rob Herring (Arm) Signed-off-by: Frank Li --- Documentation/devicetree/bindings/display/fsl,lcdif.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml index 2dd0411ec651..2b123ddf0684 100644 --- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml +++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml @@ -182,6 +182,7 @@ allOf: contains: enum: - fsl,imx28-lcdif + - fsl,imx6ul-lcdif then: properties: dmas: false -- cgit v1.2.3 From 98501598dfebb343e3c9205d30563ced989cb8ba Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 23 Jul 2026 15:14:18 -0400 Subject: ARM: dts: imx6ul-tx6ul: rename disp0 to display0 Change node name disp0 to display0 to match binding define. Fix the following CHECK_DTBS warning: arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul-0010.dtb: lcdif@21c8000 (fsl,imx6ul-lcdif): 'disp0' does not match any of the regexes: '^pinctrl-[0-9]+$' Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi index 192c6a95ae58..2f6916c0359c 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-tx6ul.dtsi @@ -369,7 +369,7 @@ display = <&display>; status = "okay"; - display: disp0 { + display: display0 { bits-per-pixel = <32>; bus-width = <24>; status = "okay"; -- cgit v1.2.3 From 4d1e805aaead7f77e36022bae757425e53076728 Mon Sep 17 00:00:00 2001 From: Mehmet Fide Date: Fri, 14 Aug 2026 09:46:57 +0200 Subject: ARM: dts: vf-colibri: apply the EXT_IO pin group pinctrl_gpio_ext describes the three Colibri EXT_IO pins, but no node references it, so the pin controller never applies it and the pads keep whatever mux and bias they came up with. It is the only pin group in the Vybrid Colibri device trees that is defined and never used. The three pins are GPIOs on gpio2 and belong to no device, so hog the group on that controller. Referencing it from &iomuxc would work too, but the pin controller would then depend on one of its own children, which fw_devlink reports as a dependency cycle. Signed-off-by: Mehmet Fide Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi b/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi index 98f9ee1b0030..74afc7b0d74b 100644 --- a/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi +++ b/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi @@ -170,6 +170,15 @@ status = "okay"; }; +&gpio2 { + /* + * EXT_IO_0..2 belong to no device, so hog the pin group here rather + * than on the pin controller, which would depend on its own child. + */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_ext>; +}; + &iomuxc { pinctrl_flexcan0: can0grp { fsl,pins = < -- cgit v1.2.3 From d376cd7c51345c4dc77d0a4ee3f533333f426400 Mon Sep 17 00:00:00 2001 From: Mehmet Fide Date: Fri, 14 Aug 2026 09:46:58 +0200 Subject: ARM: dts: vf-colibri: name the SODIMM gpio lines The Colibri modules expose most of their GPIOs on numbered SODIMM pins, and the i.MX ones already carry those numbers as gpio-line-names, so the gpiod tools print SODIMM_43 rather than a bank and an offset. Do the same for the Vybrid modules. The 99 names come from the pinout table of the Colibri VFxx datasheet (Toradex 101355). Verified on a Colibri VF50, where gpioinfo now names every pin the datasheet lists. Signed-off-by: Mehmet Fide Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi b/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi index 74afc7b0d74b..a9269857df2c 100644 --- a/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi +++ b/arch/arm/boot/dts/nxp/vf/vf-colibri.dtsi @@ -170,6 +170,44 @@ status = "okay"; }; +&gpio0 { + gpio-line-names = "", "", "SODIMM_89", "", + "", "SODIMM_102", "SODIMM_18", "SODIMM_134", + "SODIMM_16", "SODIMM_14", "SODIMM_23", "", + "", "", "SODIMM_47", "SODIMM_190", + "SODIMM_192", "SODIMM_49", "SODIMM_51", "SODIMM_53", + "SODIMM_37", "SODIMM_29", "", "SODIMM_30", + "SODIMM_20", "SODIMM_24", "SODIMM_21", "SODIMM_19", + "SODIMM_94", "SODIMM_81", "SODIMM_28"; +}; + +&gpio1 { + gpio-line-names = "SODIMM_35", "SODIMM_33", "SODIMM_27", "SODIMM_25", + "SODIMM_196", "SODIMM_194", "SODIMM_63", "SODIMM_55", + "SODIMM_65", "SODIMM_45", "SODIMM_43", "SODIMM_73", + "SODIMM_77", "SODIMM_71", "SODIMM_98", "SODIMM_101", + "SODIMM_103", "SODIMM_79", "SODIMM_97", "", + "", "SODIMM_85", "", "", + "", "", "", "", + "", "", "", "SODIMM_106"; +}; + +&gpio3 { + gpio-line-names = "SODIMM_105", "", "SODIMM_93", "", + "", "", "", "SODIMM_95", + "SODIMM_22", "SODIMM_68", "SODIMM_82", "SODIMM_56", + "SODIMM_131", "SODIMM_44", "SODIMM_144", "SODIMM_146", + "SODIMM_52", "SODIMM_54", "SODIMM_66", "SODIMM_64", + "SODIMM_57", "SODIMM_61", "SODIMM_140", "SODIMM_142", + "SODIMM_80", "SODIMM_46", "SODIMM_62", "SODIMM_48", + "SODIMM_74", "SODIMM_50", "SODIMM_136", "SODIMM_138"; +}; + +&gpio4 { + gpio-line-names = "SODIMM_76", "SODIMM_70", "SODIMM_60", "SODIMM_58", + "SODIMM_78", "SODIMM_72", "SODIMM_96"; +}; + &gpio2 { /* * EXT_IO_0..2 belong to no device, so hog the pin group here rather @@ -177,6 +215,15 @@ */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio_ext>; + + gpio-line-names = "SODIMM_69", "SODIMM_99", "SODIMM_104", "SODIMM_107", + "SODIMM_127", "SODIMM_184", "SODIMM_186", "", + "", "", "", "", + "", "", "", "SODIMM_38", + "SODIMM_36", "SODIMM_34", "SODIMM_32", "SODIMM_129", + "SODIMM_86", "SODIMM_90", "SODIMM_92", "SODIMM_88", + "SODIMM_133", "SODIMM_135", "SODIMM_188", "SODIMM_75", + "SODIMM_100"; }; &iomuxc { -- cgit v1.2.3 From 3f9c219e7539705a8d77d590ace67b8ce86264f8 Mon Sep 17 00:00:00 2001 From: Mehmet Fide Date: Fri, 14 Aug 2026 09:46:59 +0200 Subject: dt-bindings: arm: fsl: add the Colibri VF50 and VF61 on Iris The Iris is a small off-the-shelf carrier board for the Colibri family. Extend the evaluation board entries with the compatibles for a Colibri VF50 or VF61 sitting on it. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mehmet Fide Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 656f2596e1d5..46d22d45d2e6 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1737,9 +1737,11 @@ properties: - fsl,vf610 - fsl,vf610m4 - - description: Toradex Colibri VF50 Module on Colibri Evaluation Board + - description: Toradex Colibri VF50 Module on a carrier board items: - - const: toradex,vf500-colibri_vf50-on-eval + - enum: + - toradex,vf500-colibri_vf50-on-eval + - toradex,vf500-colibri-vf50-on-iris - const: toradex,vf500-colibri_vf50 - const: fsl,vf500 @@ -1751,9 +1753,11 @@ properties: - phytec,vf610-cosmic # PHYTEC Cosmic/Cosmic+ Board - const: fsl,vf610 - - description: Toradex Colibri VF61 Module on Colibri Evaluation Board + - description: Toradex Colibri VF61 Module on a carrier board items: - - const: toradex,vf610-colibri_vf61-on-eval + - enum: + - toradex,vf610-colibri_vf61-on-eval + - toradex,vf610-colibri-vf61-on-iris - const: toradex,vf610-colibri_vf61 - const: fsl,vf610 -- cgit v1.2.3 From c90f5f176da7f2a163840fd877712939dd28379f Mon Sep 17 00:00:00 2001 From: Mehmet Fide Date: Fri, 14 Aug 2026 09:47:00 +0200 Subject: ARM: dts: vf: add Iris carrier board support for Colibri VF50 and VF61 The Iris is a small off-the-shelf carrier board for the Colibri family. Describe what the board itself provides: Ethernet, one USB host and one OTG port, the pin header UARTs, i2c with the carrier RTC on it, the PWM pins on the X16 header, SPI and the microSD slot. The host port gets its VBUS through a regulator on SODIMM 129, and the two GPIOs that turn the RS232 transceivers on, SODIMM 102 and 104, are hogged. The touchscreen is an add-on rather than part of the board, so it is left out. Describe an Iris V1.1. A V2.0 carries the same signals on the same pins; what it adds, and what this does not describe, is the regulator on SODIMM 100 that can cut power to the uSD slot. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mehmet Fide Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/vf/Makefile | 2 + arch/arm/boot/dts/nxp/vf/vf-colibri-iris.dtsi | 126 ++++++++++++++++++++++++ arch/arm/boot/dts/nxp/vf/vf500-colibri-iris.dts | 14 +++ arch/arm/boot/dts/nxp/vf/vf610-colibri-iris.dts | 14 +++ 4 files changed, 156 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/vf/vf-colibri-iris.dtsi create mode 100644 arch/arm/boot/dts/nxp/vf/vf500-colibri-iris.dts create mode 100644 arch/arm/boot/dts/nxp/vf/vf610-colibri-iris.dts diff --git a/arch/arm/boot/dts/nxp/vf/Makefile b/arch/arm/boot/dts/nxp/vf/Makefile index 0a4a7f9dd43e..47be8bc318e2 100644 --- a/arch/arm/boot/dts/nxp/vf/Makefile +++ b/arch/arm/boot/dts/nxp/vf/Makefile @@ -1,8 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 dtb-$(CONFIG_SOC_VF610) += \ vf500-colibri-eval-v3.dtb \ + vf500-colibri-iris.dtb \ vf610-bk4.dtb \ vf610-colibri-eval-v3.dtb \ + vf610-colibri-iris.dtb \ vf610m4-colibri.dtb \ vf610-cosmic.dtb \ vf610m4-cosmic.dtb \ diff --git a/arch/arm/boot/dts/nxp/vf/vf-colibri-iris.dtsi b/arch/arm/boot/dts/nxp/vf/vf-colibri-iris.dtsi new file mode 100644 index 000000000000..36e34dd766ae --- /dev/null +++ b/arch/arm/boot/dts/nxp/vf/vf-colibri-iris.dtsi @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2026 Mehmet Fide + * + * Toradex Iris carrier board V1.1, common part for Colibri VF50 and VF61. + * + * The Colibri modules are pin compatible, so the carrier signals sit on the + * same SODIMM pins as they do for the i.MX modules, whose Iris device trees + * are already upstream. The two SODIMM pins below are taken from the Colibri + * VFxx datasheet (102 -> PTA12 -> PORT0[5], 104 -> PTD28 -> PORT2[2]). + * + * An Iris V2.0 carries the same signals on the same pins, so everything here + * works on it as well. What it adds is a regulator on SODIMM 100 that can cut + * power to the uSD slot, which this file does not describe. + */ + +/ { + chosen { + stdout-path = "serial0:115200n8"; + }; + + reg_usbh_vbus: regulator-usbh-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh1_reg>; + regulator-name = "VCC_USB[1-4]"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio2 19 GPIO_ACTIVE_LOW>; /* SODIMM 129, USBH_PEN */ + }; +}; + +&gpio0 { + /* + * The RS232 transceivers on the carrier are switched on by these two + * lines. Delete the hog to turn a transceiver off from userspace. + * The pin group belongs to the gpio controller rather than to iomuxc, + * which would depend on its own child and log a dependency cycle. + */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_iris_uart1_tx_on>; + + uart1-tx-on-hog { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; /* SODIMM 102 */ + output-high; + }; +}; + +&gpio2 { + pinctrl-names = "default"; + /* keep the EXT_IO group from vf-colibri.dtsi alongside ours */ + pinctrl-0 = <&pinctrl_gpio_ext>, <&pinctrl_iris_uart25_tx_on>; + + uart25-tx-on-hog { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; /* SODIMM 104 */ + output-high; + }; +}; + +&iomuxc { + pinctrl_iris_uart1_tx_on: irisuart1txongrp { + fsl,pins = < + VF610_PAD_PTA12__GPIO_5 0x22ef + >; + }; + + pinctrl_iris_uart25_tx_on: irisuart25txongrp { + fsl,pins = < + VF610_PAD_PTD28__GPIO_66 0x22ef + >; + }; +}; + +/* Colibri SSP, on the extension connector */ +&dspi1 { + status = "okay"; +}; + +&esdhc1 { + status = "okay"; +}; + +&fec1 { + status = "okay"; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + /* M41T0M6 real time clock on the carrier */ + rtc@68 { + compatible = "st,m41t0"; + reg = <0x68>; + }; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usbdev0 { + status = "okay"; +}; + +&usbh1 { + vbus-supply = <®_usbh_vbus>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/nxp/vf/vf500-colibri-iris.dts b/arch/arm/boot/dts/nxp/vf/vf500-colibri-iris.dts new file mode 100644 index 000000000000..aa91537cab37 --- /dev/null +++ b/arch/arm/boot/dts/nxp/vf/vf500-colibri-iris.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2026 Mehmet Fide + */ + +/dts-v1/; +#include "vf500-colibri.dtsi" +#include "vf-colibri-iris.dtsi" + +/ { + model = "Toradex Colibri VF50 on Iris Carrier Board"; + compatible = "toradex,vf500-colibri-vf50-on-iris", "toradex,vf500-colibri_vf50", + "fsl,vf500"; +}; diff --git a/arch/arm/boot/dts/nxp/vf/vf610-colibri-iris.dts b/arch/arm/boot/dts/nxp/vf/vf610-colibri-iris.dts new file mode 100644 index 000000000000..7db5aa490966 --- /dev/null +++ b/arch/arm/boot/dts/nxp/vf/vf610-colibri-iris.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2026 Mehmet Fide + */ + +/dts-v1/; +#include "vf610-colibri.dtsi" +#include "vf-colibri-iris.dtsi" + +/ { + model = "Toradex Colibri VF61 on Iris Carrier Board"; + compatible = "toradex,vf610-colibri-vf61-on-iris", "toradex,vf610-colibri_vf61", + "fsl,vf610"; +}; -- cgit v1.2.3 From dc5bfc682b4df23b105ceacd387865a42099aba9 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 21 Aug 2026 10:28:09 +0200 Subject: ARM: imx: Replace __ASSEMBLY__ with __ASSEMBLER__ While the GCC and Clang compilers already define __ASSEMBLER__ auto- matically when compiling assembly code, __ASSEMBLY__ is a macro that only gets defined by the Makefiles in the kernel. This can be very confusing when switching between userspace and kernelspace coding, or when dealing with uapi headers that rather should use __ASSEMBLER__ instead. Let's standardize now on the __ASSEMBLER__ macro to avoid this confusion. Signed-off-by: Thomas Huth Signed-off-by: Frank Li --- arch/arm/mach-imx/hardware.h | 2 +- arch/arm/mach-imx/mxc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h index 0760fff39a0b..71f09648c777 100644 --- a/arch/arm/mach-imx/hardware.h +++ b/arch/arm/mach-imx/hardware.h @@ -7,7 +7,7 @@ #ifndef __ASM_ARCH_MXC_HARDWARE_H__ #define __ASM_ARCH_MXC_HARDWARE_H__ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include #include #endif diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index fe2d0f5abfcc..1d13e3959159 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -16,7 +16,7 @@ #define IMX_DDR_TYPE_LPDDR2 1 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #ifdef CONFIG_SOC_IMX6SL static inline bool cpu_is_imx6sl(void) -- cgit v1.2.3 From 9d183de1df061377bf5d29f33dc4814382187649 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 19 Jun 2026 14:24:48 +0200 Subject: soc: imx: Replace __ASSEMBLY__ with __ASSEMBLER__ in header file While the GCC and Clang compilers already define __ASSEMBLER__ automatically when compiling assembly code, __ASSEMBLY__ is a macro that only gets defined by the Makefiles in the kernel. This can be very confusing when switching between userspace and kernelspace coding, or when dealing with uapi headers that rather should use __ASSEMBLER__ instead. So let's standardize now on the __ASSEMBLER__ macro that is provided by the compilers. This is a completely mechanical patch (done with a simple "sed -i" statement). Signed-off-by: Thomas Huth Signed-off-by: Frank Li --- include/soc/imx/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/soc/imx/cpu.h b/include/soc/imx/cpu.h index 0bf610acafd0..8c53150acd76 100644 --- a/include/soc/imx/cpu.h +++ b/include/soc/imx/cpu.h @@ -30,7 +30,7 @@ #define MXC_CPU_VF600 0x600 #define MXC_CPU_VF610 (MXC_CPU_VF600 | MXC_CPU_VFx10) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ extern unsigned int __mxc_cpu_type; #endif -- cgit v1.2.3 From 1c3f5701bc0ff5cbe56bdae76157047d47051d44 Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Mon, 31 Aug 2026 07:12:22 +0200 Subject: arm64: dts: imx8mp-phyboard-pollux-peb-av-10: Fix SAI master assignment The dailink_master label was placed on the codec sub-node instead of the CPU sub-node, configuring the codec as I2S bitclock/frame master with SAI2 as slave. On this board, BCLK and LRCLK are wired the other way around: SAI2 must be bus master, with the codec as I2S slave. Move dailink_master to the CPU sub-node so SAI2 drives BCLK and LRCLK, fixing broken audio on the PHYTEC phyBOARD-Pollux-i.MX8MP board with PEB-AV-10 Audio/Video expansion board. Also remove the spurious clocks property from the codec sub-node, which had no effect in this topology. Fixes: 7012f551081f ("arm64: dts: imx8mp pollux: add expansion board overlay") Signed-off-by: Primoz Fiser Reviewed-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-av-10.dtsi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-av-10.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-av-10.dtsi index bb740f845855..8957b24a7ad2 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-av-10.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-av-10.dtsi @@ -77,13 +77,12 @@ "MIC3R", "Microphone Jack", "Microphone Jack", "Mic Bias"; - simple-audio-card,cpu { + dailink_master: simple-audio-card,cpu { sound-dai = <&sai2>; }; - dailink_master: simple-audio-card,codec { + simple-audio-card,codec { sound-dai = <&codec>; - clocks = <&clk IMX8MP_CLK_SAI2>; }; }; }; -- cgit v1.2.3 From 9094eb07b3e236233dbaac61ed30cc65be9e9c6c Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Fri, 21 Aug 2026 13:43:32 +0800 Subject: arm64: dts: imx95: Avoid 32-bit PCIe window System RAM overlap Move the PCIe non-prefetchable memory PCI bus address from 0xe0000000 to 0x10000000 to avoid overlap with DRAM. Avoid hit this as a P2P transfer[1]. The 0x10000000 range is reserved and safe to use. Fixes: dbecf38e60d4e ("arm64: dts: imx95: Correct PCIe outbound address space configuration") Signed-off-by: Richard Zhu Link: https://lore.kernel.org/imx/753fca23-c3eb-45e3-aeac-b7b248fa723a@app.fastmail.com/ [1] Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi index 54a3e2804dae..1cb8eb15e5c7 100644 --- a/arch/arm64/boot/dts/freescale/imx95.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi @@ -1948,7 +1948,7 @@ <0 0x4c340000 0 0x4000>; reg-names = "dbi", "config", "atu", "app"; ranges = <0x43000000 0x9 0x00000000 0x9 0x00000000 0x0 0xe0000000>, - <0x82000000 0x0 0xe0000000 0x9 0xe0000000 0x0 0x10000000>, + <0x82000000 0x0 0x10000000 0x9 0xe0000000 0x0 0x10000000>, <0x81000000 0x0 0x00000000 0x9 0xf0000000 0x0 0x00100000>; #address-cells = <3>; #size-cells = <2>; @@ -2039,7 +2039,7 @@ <0 0x4c3c0000 0 0x4000>; reg-names = "dbi", "config", "atu", "app"; ranges = <0x43000000 0xa 0x00000000 0xa 0x00000000 0x0 0xe0000000>, - <0x82000000 0x0 0xe0000000 0xa 0xe0000000 0x0 0x10000000>, + <0x82000000 0x0 0x10000000 0xa 0xe0000000 0x0 0x10000000>, <0x81000000 0x0 0x00000000 0xa 0xf0000000 0x0 0x00100000>; #address-cells = <3>; #size-cells = <2>; -- cgit v1.2.3 From 775ebd246092294432895f8e9bd48e3f0a56714a Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Fri, 21 Aug 2026 13:43:33 +0800 Subject: arm64: dts: imx94: Avoid 32-bit PCIe window System RAM overlap Move the PCIe non-prefetchable memory PCI bus address from 0xe0000000 to 0x10000000 to avoid overlap with DRAM. Avoid hit this as a P2P transfer[1]. The 0x10000000 range is reserved and safe to use. Link: https://lore.kernel.org/imx/753fca23-c3eb-45e3-aeac-b7b248fa723a@app.fastmail.com/ [1] Fixes: ffccbd6804e88 ("arm64: dts: imx94: Correct PCIe outbound address space configuration") Signed-off-by: Richard Zhu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx94.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx94.dtsi b/arch/arm64/boot/dts/freescale/imx94.dtsi index 34833e62bd79..afaaf70417d2 100644 --- a/arch/arm64/boot/dts/freescale/imx94.dtsi +++ b/arch/arm64/boot/dts/freescale/imx94.dtsi @@ -1379,7 +1379,7 @@ <0 0x4c340000 0 0x4000>; reg-names = "dbi", "config", "atu", "app"; ranges = <0x43000000 0x9 0x00000000 0x9 0x00000000 0x0 0xe0000000>, - <0x82000000 0x0 0xe0000000 0x9 0xe0000000 0x0 0x10000000>, + <0x82000000 0x0 0x10000000 0x9 0xe0000000 0x0 0x10000000>, <0x81000000 0x0 0x00000000 0x9 0xf0000000 0x0 0x00100000>; #address-cells = <3>; #size-cells = <2>; -- cgit v1.2.3 From fff67007ad5403966092006867fe9926aaedda0d Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Fri, 21 Aug 2026 13:43:34 +0800 Subject: arm64: dts: imx943: Avoid 32-bit PCIe window System RAM overlap Move the PCIe non-prefetchable memory PCI bus address from 0xe0000000 to 0x10000000 to avoid overlap with DRAM. Avoid hit this as a P2P transfer[1]. The 0x10000000 range is reserved and safe to use. Link: https://lore.kernel.org/imx/753fca23-c3eb-45e3-aeac-b7b248fa723a@app.fastmail.com/ [1] Fixes: 6de3a7d7a4f65 ("arm64: dts: imx943: Correct PCIe outbound address space configuration") Signed-off-by: Richard Zhu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx943.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx943.dtsi b/arch/arm64/boot/dts/freescale/imx943.dtsi index 01152fd0efa5..a564488d9cd7 100644 --- a/arch/arm64/boot/dts/freescale/imx943.dtsi +++ b/arch/arm64/boot/dts/freescale/imx943.dtsi @@ -219,7 +219,7 @@ <0 0x4c3c0000 0 0x4000>; reg-names = "dbi", "config", "atu", "app"; ranges = <0x43000000 0xa 0x00000000 0xa 0x00000000 0x0 0xe0000000>, - <0x82000000 0x0 0xe0000000 0xa 0xe0000000 0x0 0x10000000>, + <0x82000000 0x0 0x10000000 0xa 0xe0000000 0x0 0x10000000>, <0x81000000 0x0 0x00000000 0xa 0xf0000000 0x0 0x00100000>; #address-cells = <3>; #size-cells = <2>; -- cgit v1.2.3 From 323b12f8c78c61538b36e372f25be46655177d29 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 Aug 2026 23:34:39 +0200 Subject: arm64: dts: imx8mn: Expand EEPROM description on ifm VHIP4 EvalBoard Describe the EEPROM write protect GPIOs and labels on VHIP4 EvalBoard. Signed-off-by: Marek Vasut Reviewed-by: Bartosz Golaszewski Signed-off-by: Frank Li --- .../freescale/imx8mn-vhip4-evalboard-common.dtsi | 3 ++- .../dts/freescale/imx8mn-vhip4-evalboard-v1.dts | 8 +++++++ .../dts/freescale/imx8mn-vhip4-evalboard-v2.dts | 28 ++++++++++++++++++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-common.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-common.dtsi index aaf9761703aa..d420ab398b22 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-common.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-common.dtsi @@ -142,9 +142,10 @@ pinctrl-0 = <&pinctrl_i2c1>; pinctrl-1 = <&pinctrl_i2c1_gpio>; - eeprom@51 { + cfg_eeprom: eeprom@51 { compatible = "atmel,24c128"; reg = <0x51>; + label = "ifm-deviceinfo"; }; hw_rtc: rtc@52 { diff --git a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v1.dts b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v1.dts index a8f7c226a61f..363f487f8c84 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v1.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v1.dts @@ -13,6 +13,11 @@ "ifm,imx8mn-vhip4", "fsl,imx8mn"; }; +&cfg_eeprom { + /* Shared with logging EEPROM on v1 hardware */ + wp-gpios = <&gpio5 20 GPIO_ACTIVE_HIGH>; +}; + &ifm_led { pinctrl-1 = <&pinctrl_gpio_led_v1>; @@ -91,6 +96,9 @@ eeprom@50 { compatible = "atmel,24c128"; reg = <0x50>; + label = "ifm-logging"; + /* Shared with configuration EEPROM on v1 hardware */ + wp-gpios = <&gpio5 20 GPIO_ACTIVE_HIGH>; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v2.dts b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v2.dts index 43fd4d0041ef..0fcffd168f6a 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v2.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-evalboard-v2.dts @@ -20,6 +20,12 @@ }; }; +&cfg_eeprom { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cfgeeprom>; + wp-gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>; +}; + &ifm_led { pinctrl-1 = <&pinctrl_gpio_led_v2>; @@ -88,6 +94,10 @@ eeprom@54 { compatible = "atmel,24c128"; reg = <0x54>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_logeeprom>; + label = "ifm-logging"; + wp-gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>; }; }; @@ -103,6 +113,13 @@ }; &iomuxc { + pinctrl_cfgeeprom: cfgeeprom-grp { + fsl,pins = < + /* CFG_EEPROM_WP */ + MX8MN_IOMUXC_SD1_STROBE_GPIO2_IO11 0x140 + >; + }; + pinctrl_ecspi1_cs: ecspi1-cs-grp { fsl,pins = < /* KS8794 nCS */ @@ -143,12 +160,8 @@ fsl,pins = < MX8MN_IOMUXC_SD1_DATA4_GPIO2_IO6 0x56 MX8MN_IOMUXC_SD1_DATA5_GPIO2_IO7 0xd6 - /* CFG_EEPROM_WP */ - MX8MN_IOMUXC_SD1_STROBE_GPIO2_IO11 0x140 /* RTC_nIRQ */ MX8MN_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x116 - /* LOG_EE_WP */ - MX8MN_IOMUXC_SPDIF_TX_GPIO5_IO3 0x140 >; }; @@ -166,6 +179,13 @@ >; }; + pinctrl_logeeprom: logeeprom-grp { + fsl,pins = < + /* LOG_EE_WP */ + MX8MN_IOMUXC_SPDIF_TX_GPIO5_IO3 0x140 + >; + }; + pinctrl_mcp2518: mcp2518-grp { fsl,pins = < /* CAN0_CLKO */ -- cgit v1.2.3 From cc7fefa70818c7a9fa2cdc5487d9a80d69b1d773 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:40:24 +0200 Subject: arm64: dts: imx8mq: Replace spaces indentation with tabs Replace excessive spaces for aligning indentation into tabs. This will be reported by dt-style-check ("[mixed-indent-chars] too many space characters in indent (more than 7)"). Signed-off-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- .../arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi | 16 +- arch/arm64/boot/dts/freescale/imx8mq.dtsi | 168 ++++++++++----------- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi index c7bbba45f368..a272c1bd7548 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi @@ -99,7 +99,7 @@ regulator-max-microvolt = <1000000>; gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; states = <1000000 0x1 - 900000 0x0>; + 900000 0x0>; regulator-always-on; }; @@ -295,7 +295,7 @@ reg = <0x32>; interrupt-parent = <&gpio3>; interrupts = <17 IRQ_TYPE_EDGE_BOTH>, - <18 IRQ_TYPE_EDGE_FALLING>; + <18 IRQ_TYPE_EDGE_FALLING>; interrupt-names = "a_det", "alert"; }; @@ -549,9 +549,9 @@ pinctrl-0 = <&pinctrl_pcie0>; reset-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; clocks = <&clk IMX8MQ_CLK_PCIE1_ROOT>, - <&pcie0_refclk>, - <&clk IMX8MQ_CLK_PCIE1_PHY>, - <&clk IMX8MQ_CLK_PCIE1_AUX>; + <&pcie0_refclk>, + <&clk IMX8MQ_CLK_PCIE1_PHY>, + <&clk IMX8MQ_CLK_PCIE1_AUX>; vph-supply = <&vgen5_reg>; status = "okay"; }; @@ -561,9 +561,9 @@ pinctrl-0 = <&pinctrl_pcie1>; reset-gpio = <&gpio1 6 GPIO_ACTIVE_LOW>; clocks = <&clk IMX8MQ_CLK_PCIE2_ROOT>, - <&pcie1_refclk>, - <&clk IMX8MQ_CLK_PCIE2_PHY>, - <&clk IMX8MQ_CLK_PCIE2_AUX>; + <&pcie1_refclk>, + <&clk IMX8MQ_CLK_PCIE2_PHY>, + <&clk IMX8MQ_CLK_PCIE2_AUX>; vph-supply = <&vgen5_reg>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi index d75710cdb5b4..5545b5b20ab2 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi @@ -363,9 +363,9 @@ timer { compatible = "arm,armv8-timer"; interrupts = , /* Physical Secure */ - , /* Physical Non-Secure */ - , /* Virtual */ - ; /* Hypervisor */ + , /* Physical Non-Secure */ + , /* Virtual */ + ; /* Hypervisor */ interrupt-parent = <&gic>; arm,no-tick-in-suspend; }; @@ -531,8 +531,8 @@ reg = <0x30010000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_SAI1_IPG>, - <&clk IMX8MQ_CLK_SAI1_ROOT>, - <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; + <&clk IMX8MQ_CLK_SAI1_ROOT>, + <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dmas = <&sdma2 8 24 0>, <&sdma1 9 24 0>; dma-names = "rx", "tx"; @@ -545,8 +545,8 @@ reg = <0x30030000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_SAI6_IPG>, - <&clk IMX8MQ_CLK_SAI6_ROOT>, - <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; + <&clk IMX8MQ_CLK_SAI6_ROOT>, + <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dmas = <&sdma2 4 24 0>, <&sdma2 5 24 0>; dma-names = "rx", "tx"; @@ -559,8 +559,8 @@ reg = <0x30040000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_SAI5_IPG>, - <&clk IMX8MQ_CLK_SAI5_ROOT>, - <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; + <&clk IMX8MQ_CLK_SAI5_ROOT>, + <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dmas = <&sdma2 2 24 0>, <&sdma2 3 24 0>; dma-names = "rx", "tx"; @@ -573,8 +573,8 @@ reg = <0x30050000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_SAI4_IPG>, - <&clk IMX8MQ_CLK_SAI4_ROOT>, - <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; + <&clk IMX8MQ_CLK_SAI4_ROOT>, + <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dmas = <&sdma2 0 24 0>, <&sdma2 1 24 0>; dma-names = "rx", "tx"; @@ -585,7 +585,7 @@ compatible = "fsl,imx8mq-gpio", "fsl,imx35-gpio"; reg = <0x30200000 0x10000>; interrupts = , - ; + ; clocks = <&clk IMX8MQ_CLK_GPIO1_ROOT>; gpio-controller; #gpio-cells = <2>; @@ -598,7 +598,7 @@ compatible = "fsl,imx8mq-gpio", "fsl,imx35-gpio"; reg = <0x30210000 0x10000>; interrupts = , - ; + ; clocks = <&clk IMX8MQ_CLK_GPIO2_ROOT>; gpio-controller; #gpio-cells = <2>; @@ -611,7 +611,7 @@ compatible = "fsl,imx8mq-gpio", "fsl,imx35-gpio"; reg = <0x30220000 0x10000>; interrupts = , - ; + ; clocks = <&clk IMX8MQ_CLK_GPIO3_ROOT>; gpio-controller; #gpio-cells = <2>; @@ -624,7 +624,7 @@ compatible = "fsl,imx8mq-gpio", "fsl,imx35-gpio"; reg = <0x30230000 0x10000>; interrupts = , - ; + ; clocks = <&clk IMX8MQ_CLK_GPIO4_ROOT>; gpio-controller; #gpio-cells = <2>; @@ -637,7 +637,7 @@ compatible = "fsl,imx8mq-gpio", "fsl,imx35-gpio"; reg = <0x30240000 0x10000>; interrupts = , - ; + ; clocks = <&clk IMX8MQ_CLK_GPIO5_ROOT>; gpio-controller; #gpio-cells = <2>; @@ -845,14 +845,14 @@ compatible = "fsl,imx8mq-ccm"; reg = <0x30380000 0x10000>; interrupts = , - ; + ; #clock-cells = <1>; clocks = <&ckil>, <&osc_25m>, <&osc_27m>, - <&clk_ext1>, <&clk_ext2>, - <&clk_ext3>, <&clk_ext4>; + <&clk_ext1>, <&clk_ext2>, + <&clk_ext3>, <&clk_ext4>; clock-names = "ckil", "osc_25m", "osc_27m", - "clk_ext1", "clk_ext2", - "clk_ext3", "clk_ext4"; + "clk_ext1", "clk_ext2", + "clk_ext3", "clk_ext4"; assigned-clocks = <&clk IMX8MQ_CLK_A53_SRC>, <&clk IMX8MQ_CLK_A53_CORE>, <&clk IMX8MQ_CLK_NOC>, @@ -940,9 +940,9 @@ #power-domain-cells = <0>; reg = ; clocks = <&clk IMX8MQ_CLK_GPU_ROOT>, - <&clk IMX8MQ_CLK_GPU_SHADER_DIV>, + <&clk IMX8MQ_CLK_GPU_SHADER_DIV>, <&clk IMX8MQ_CLK_GPU_AXI>, - <&clk IMX8MQ_CLK_GPU_AHB>; + <&clk IMX8MQ_CLK_GPU_AHB>; }; pgc_vpu: power-domain@6 { @@ -1000,7 +1000,7 @@ reg = <0x30660000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_PWM1_ROOT>, - <&clk IMX8MQ_CLK_PWM1_ROOT>; + <&clk IMX8MQ_CLK_PWM1_ROOT>; clock-names = "ipg", "per"; #pwm-cells = <3>; status = "disabled"; @@ -1011,7 +1011,7 @@ reg = <0x30670000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_PWM2_ROOT>, - <&clk IMX8MQ_CLK_PWM2_ROOT>; + <&clk IMX8MQ_CLK_PWM2_ROOT>; clock-names = "ipg", "per"; #pwm-cells = <3>; status = "disabled"; @@ -1022,7 +1022,7 @@ reg = <0x30680000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_PWM3_ROOT>, - <&clk IMX8MQ_CLK_PWM3_ROOT>; + <&clk IMX8MQ_CLK_PWM3_ROOT>; clock-names = "ipg", "per"; #pwm-cells = <3>; status = "disabled"; @@ -1033,7 +1033,7 @@ reg = <0x30690000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_PWM4_ROOT>, - <&clk IMX8MQ_CLK_PWM4_ROOT>; + <&clk IMX8MQ_CLK_PWM4_ROOT>; clock-names = "ipg", "per"; #pwm-cells = <3>; status = "disabled"; @@ -1124,11 +1124,11 @@ uart1: serial@30860000 { compatible = "fsl,imx8mq-uart", - "fsl,imx6q-uart"; + "fsl,imx6q-uart"; reg = <0x30860000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_UART1_ROOT>, - <&clk IMX8MQ_CLK_UART1_ROOT>; + <&clk IMX8MQ_CLK_UART1_ROOT>; clock-names = "ipg", "per"; dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>; dma-names = "rx", "tx"; @@ -1137,11 +1137,11 @@ uart3: serial@30880000 { compatible = "fsl,imx8mq-uart", - "fsl,imx6q-uart"; + "fsl,imx6q-uart"; reg = <0x30880000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_UART3_ROOT>, - <&clk IMX8MQ_CLK_UART3_ROOT>; + <&clk IMX8MQ_CLK_UART3_ROOT>; clock-names = "ipg", "per"; dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>; dma-names = "rx", "tx"; @@ -1150,11 +1150,11 @@ uart2: serial@30890000 { compatible = "fsl,imx8mq-uart", - "fsl,imx6q-uart"; + "fsl,imx6q-uart"; reg = <0x30890000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_UART2_ROOT>, - <&clk IMX8MQ_CLK_UART2_ROOT>; + <&clk IMX8MQ_CLK_UART2_ROOT>; clock-names = "ipg", "per"; dmas = <&sdma1 24 4 0>, <&sdma1 25 4 0>; dma-names = "rx", "tx"; @@ -1205,8 +1205,8 @@ reg = <0x308c0000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_SAI3_IPG>, - <&clk IMX8MQ_CLK_SAI3_ROOT>, - <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; + <&clk IMX8MQ_CLK_SAI3_ROOT>, + <&clk IMX8MQ_CLK_DUMMY>, <&clk IMX8MQ_CLK_DUMMY>; clock-names = "bus", "mclk1", "mclk2", "mclk3"; dmas = <&sdma1 12 24 0>, <&sdma1 13 24 0>; dma-names = "rx", "tx"; @@ -1356,11 +1356,11 @@ uart4: serial@30a60000 { compatible = "fsl,imx8mq-uart", - "fsl,imx6q-uart"; + "fsl,imx6q-uart"; reg = <0x30a60000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_UART4_ROOT>, - <&clk IMX8MQ_CLK_UART4_ROOT>; + <&clk IMX8MQ_CLK_UART4_ROOT>; clock-names = "ipg", "per"; dmas = <&sdma1 28 4 0>, <&sdma1 29 4 0>; dma-names = "rx", "tx"; @@ -1481,12 +1481,12 @@ usdhc1: mmc@30b40000 { compatible = "fsl,imx8mq-usdhc", - "fsl,imx7d-usdhc"; + "fsl,imx7d-usdhc"; reg = <0x30b40000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_IPG_ROOT>, - <&clk IMX8MQ_CLK_NAND_USDHC_BUS>, - <&clk IMX8MQ_CLK_USDHC1_ROOT>; + <&clk IMX8MQ_CLK_NAND_USDHC_BUS>, + <&clk IMX8MQ_CLK_USDHC1_ROOT>; clock-names = "ipg", "ahb", "per"; fsl,tuning-start-tap = <20>; fsl,tuning-step = <2>; @@ -1496,12 +1496,12 @@ usdhc2: mmc@30b50000 { compatible = "fsl,imx8mq-usdhc", - "fsl,imx7d-usdhc"; + "fsl,imx7d-usdhc"; reg = <0x30b50000 0x10000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_IPG_ROOT>, - <&clk IMX8MQ_CLK_NAND_USDHC_BUS>, - <&clk IMX8MQ_CLK_USDHC2_ROOT>; + <&clk IMX8MQ_CLK_NAND_USDHC_BUS>, + <&clk IMX8MQ_CLK_USDHC2_ROOT>; clock-names = "ipg", "ahb", "per"; fsl,tuning-start-tap = <20>; fsl,tuning-step = <2>; @@ -1538,16 +1538,16 @@ compatible = "fsl,imx8mq-fec", "fsl,imx6sx-fec"; reg = <0x30be0000 0x10000>; interrupts = , - , + , , ; clocks = <&clk IMX8MQ_CLK_ENET1_ROOT>, - <&clk IMX8MQ_CLK_ENET1_ROOT>, - <&clk IMX8MQ_CLK_ENET_TIMER>, - <&clk IMX8MQ_CLK_ENET_REF>, - <&clk IMX8MQ_CLK_ENET_PHY_REF>; + <&clk IMX8MQ_CLK_ENET1_ROOT>, + <&clk IMX8MQ_CLK_ENET_TIMER>, + <&clk IMX8MQ_CLK_ENET_REF>, + <&clk IMX8MQ_CLK_ENET_PHY_REF>; clock-names = "ipg", "ahb", "ptp", - "enet_clk_ref", "enet_out"; + "enet_clk_ref", "enet_out"; assigned-clocks = <&clk IMX8MQ_CLK_ENET_AXI>, <&clk IMX8MQ_CLK_ENET_TIMER>, <&clk IMX8MQ_CLK_ENET_REF>, @@ -1639,23 +1639,23 @@ reg = <0x38000000 0x40000>; interrupts = ; clocks = <&clk IMX8MQ_CLK_GPU_ROOT>, - <&clk IMX8MQ_CLK_GPU_SHADER_DIV>, - <&clk IMX8MQ_CLK_GPU_AXI>, - <&clk IMX8MQ_CLK_GPU_AHB>; + <&clk IMX8MQ_CLK_GPU_SHADER_DIV>, + <&clk IMX8MQ_CLK_GPU_AXI>, + <&clk IMX8MQ_CLK_GPU_AHB>; clock-names = "core", "shader", "bus", "reg"; #cooling-cells = <2>; assigned-clocks = <&clk IMX8MQ_CLK_GPU_CORE_SRC>, - <&clk IMX8MQ_CLK_GPU_SHADER_SRC>, - <&clk IMX8MQ_CLK_GPU_AXI>, - <&clk IMX8MQ_CLK_GPU_AHB>, - <&clk IMX8MQ_GPU_PLL_BYPASS>; + <&clk IMX8MQ_CLK_GPU_SHADER_SRC>, + <&clk IMX8MQ_CLK_GPU_AXI>, + <&clk IMX8MQ_CLK_GPU_AHB>, + <&clk IMX8MQ_GPU_PLL_BYPASS>; assigned-clock-parents = <&clk IMX8MQ_GPU_PLL_OUT>, - <&clk IMX8MQ_GPU_PLL_OUT>, - <&clk IMX8MQ_GPU_PLL_OUT>, - <&clk IMX8MQ_GPU_PLL_OUT>, - <&clk IMX8MQ_GPU_PLL>; + <&clk IMX8MQ_GPU_PLL_OUT>, + <&clk IMX8MQ_GPU_PLL_OUT>, + <&clk IMX8MQ_GPU_PLL_OUT>, + <&clk IMX8MQ_GPU_PLL>; assigned-clock-rates = <800000000>, <800000000>, - <800000000>, <400000000>, <0>; + <800000000>, <400000000>, <0>; power-domains = <&pgc_gpu>; }; @@ -1663,13 +1663,13 @@ compatible = "fsl,imx8mq-dwc3", "snps,dwc3"; reg = <0x38100000 0x10000>; clocks = <&clk IMX8MQ_CLK_USB1_CTRL_ROOT>, - <&clk IMX8MQ_CLK_USB_CORE_REF>, + <&clk IMX8MQ_CLK_USB_CORE_REF>, <&clk IMX8MQ_CLK_32K>; clock-names = "bus_early", "ref", "suspend"; assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS>, - <&clk IMX8MQ_CLK_USB_CORE_REF>; + <&clk IMX8MQ_CLK_USB_CORE_REF>; assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_500M>, - <&clk IMX8MQ_SYS1_PLL_100M>; + <&clk IMX8MQ_SYS1_PLL_100M>; assigned-clock-rates = <500000000>, <100000000>; interrupts = ; phys = <&usb3_phy0>, <&usb3_phy0>; @@ -1695,13 +1695,13 @@ compatible = "fsl,imx8mq-dwc3", "snps,dwc3"; reg = <0x38200000 0x10000>; clocks = <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>, - <&clk IMX8MQ_CLK_USB_CORE_REF>, + <&clk IMX8MQ_CLK_USB_CORE_REF>, <&clk IMX8MQ_CLK_32K>; clock-names = "bus_early", "ref", "suspend"; assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS>, - <&clk IMX8MQ_CLK_USB_CORE_REF>; + <&clk IMX8MQ_CLK_USB_CORE_REF>; assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_500M>, - <&clk IMX8MQ_SYS1_PLL_100M>; + <&clk IMX8MQ_SYS1_PLL_100M>; assigned-clock-rates = <500000000>, <100000000>; interrupts = ; phys = <&usb3_phy1>, <&usb3_phy1>; @@ -1767,9 +1767,9 @@ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &gic GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &gic GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &gic GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &gic GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; + <0 0 0 2 &gic GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; fsl,max-link-speed = <2>; linux,pci-domain = <0>; clocks = <&clk IMX8MQ_CLK_PCIE1_ROOT>, @@ -1779,17 +1779,17 @@ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux"; power-domains = <&pgc_pcie>; resets = <&src IMX8MQ_RESET_PCIEPHY>, - <&src IMX8MQ_RESET_PCIE_CTRL_APPS_EN>, - <&src IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF>; + <&src IMX8MQ_RESET_PCIE_CTRL_APPS_EN>, + <&src IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF>; reset-names = "pciephy", "apps", "turnoff"; assigned-clocks = <&clk IMX8MQ_CLK_PCIE1_CTRL>, - <&clk IMX8MQ_CLK_PCIE1_PHY>, - <&clk IMX8MQ_CLK_PCIE1_AUX>; + <&clk IMX8MQ_CLK_PCIE1_PHY>, + <&clk IMX8MQ_CLK_PCIE1_AUX>; assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_250M>, - <&clk IMX8MQ_SYS2_PLL_100M>, - <&clk IMX8MQ_SYS1_PLL_80M>; + <&clk IMX8MQ_SYS2_PLL_100M>, + <&clk IMX8MQ_SYS1_PLL_80M>; assigned-clock-rates = <250000000>, <100000000>, - <10000000>; + <10000000>; status = "disabled"; pcie0_port0: pcie@0 { @@ -1868,17 +1868,17 @@ clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux"; power-domains = <&pgc_pcie>; resets = <&src IMX8MQ_RESET_PCIEPHY2>, - <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_EN>, - <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF>; + <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_EN>, + <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF>; reset-names = "pciephy", "apps", "turnoff"; assigned-clocks = <&clk IMX8MQ_CLK_PCIE2_CTRL>, - <&clk IMX8MQ_CLK_PCIE2_PHY>, - <&clk IMX8MQ_CLK_PCIE2_AUX>; + <&clk IMX8MQ_CLK_PCIE2_PHY>, + <&clk IMX8MQ_CLK_PCIE2_AUX>; assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_250M>, - <&clk IMX8MQ_SYS2_PLL_100M>, - <&clk IMX8MQ_SYS1_PLL_80M>; + <&clk IMX8MQ_SYS2_PLL_100M>, + <&clk IMX8MQ_SYS1_PLL_80M>; assigned-clock-rates = <250000000>, <100000000>, - <10000000>; + <10000000>; status = "disabled"; pcie1_port0: pcie@0 { -- cgit v1.2.3 From 8188a59dd6782786556b18f515090b79cb701c45 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 24 Aug 2026 23:25:29 +0200 Subject: arm64: dts: lx2160a: fix incorrect pinmux For gpio1 value set for pinctrl is outside the mask and so will do nothing. Add the missing offset for value field to be the same as the mask as expected. Fixes: 284ad7064aaa ("arm64: dts: lx2160a: complete pinmux for rcwsr12 configuration word") Suggested-by: Thibaut Collet Reviewed-by: Josua Mayer Signed-off-by: Vincent Jardin Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi index ae6e37870c5e..d4522a19405a 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi @@ -1622,7 +1622,7 @@ }; gpio1_31_28_pins: xspi1-data74-gpio-pins { - pinctrl-single,bits = <0x0 0x1 (0x7 << 15)>; + pinctrl-single,bits = <0x0 (0x1 << 15) (0x7 << 15)>; }; fspi_data30_pins: xspi1-data30-pins { @@ -1630,7 +1630,7 @@ }; gpio1_27_24_pins: xspi1-data30-gpio-pins { - pinctrl-single,bits = <0x0 0x1 (0x7 << 18)>; + pinctrl-single,bits = <0x0 (0x1 << 18) (0x7 << 18)>; }; fspi_dqs_sck_cs10_pins: xspi1-base-pins { @@ -1638,7 +1638,7 @@ }; gpio1_23_20_pins: xspi1-base-gpio-pins { - pinctrl-single,bits = <0x0 0x1 (0x7 << 21)>; + pinctrl-single,bits = <0x0 (0x1 << 21) (0x7 << 21)>; }; esdhc0_cmd_data30_clk_vsel_pins: sdhc1-base-sdhc-vsel-pins { -- cgit v1.2.3 From 6affdda171ca8f2e082e8c4fba56233a2f8c9910 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 24 Aug 2026 23:25:30 +0200 Subject: arm64: dts: lx2160a: fix IIC1 pinmux submask rejected by pinctrl-single IIC1_PMUX is a single bit field at RCWSR14 bit 10, so the mask for the two iic1 pinmux nodes was narrowed from 0x7 to 0x1 to avoid writing the two reserved bits next to it. With pinctrl-single,bit-per-mux the driver does not take the supplied mask as the bits to modify. It derives the field from the node's pinctrl-single,function-mask, which is 0x7 here, and then requires the supplied mask to match it exactly: bit_pos = __ffs(mask); /* 10 */ mask_pos = ((pcs->fmask) << bit_pos); /* 0x7 << 10 = 0x1c00 */ submask = mask & mask_pos; /* 0x400 */ ... if (submask != mask_pos) { dev_warn(pcs->dev, "Invalid submask 0x%x for %pOFn at 0x%x\n", submask, np, offset); continue; } A one bit mask gives submask 0x400 against mask_pos 0x1c00, so both nodes are rejected and the pins are never muxed with this message: pinctrl-single 70010012c.pinmux: Invalid submask 0x400 for iic1-i2c-pins pinctrl-single 70010012c.pinmux: Invalid submask 0x400 for iic1-gpio-pins The values are not changed: - 0x0 selects IIC1 - 0x1 << 10 selects GPIO_1[3:2]. Fixes: 7a3cc49ad1fc ("arm64: dts: lx2160a: change i2c0 (iic1) pinmux mask to one bit") Signed-off-by: Vincent Jardin Reviewed-by: Josua Mayer Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi index d4522a19405a..d9d4500a4051 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi @@ -1687,12 +1687,19 @@ }; /* RCWSR14 */ + /* + * IIC1_PMUX is a single bit at RCWSR14[10], but bit-per-mux + * uses the mask for the field to clear before applying the + * value. + * So bits 11 and 12, which are reserved, are written as 0 + * on every mux switch, it is harmless. + */ i2c0_pins: iic1-i2c-pins { - pinctrl-single,bits = <0x8 0x0 (0x1 << 10)>; + pinctrl-single,bits = <0x8 0x0 (0x7 << 10)>; }; gpio0_3_2_pins: iic1-gpio-pins { - pinctrl-single,bits = <0x8 (0x1 << 10) (0x1 << 10)>; + pinctrl-single,bits = <0x8 (0x1 << 10) (0x7 << 10)>; }; }; -- cgit v1.2.3 From f14f4dc8ea3810f8ed4f0f3ea13f8bba3e2b0f04 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 24 Aug 2026 23:25:31 +0200 Subject: arm64: dts: lx2160a: fix the iic5 spi3 pinmux offset and value The iic5-spi3-pins node has both of its first two cells wrong. The offset selects the register within the node's reg range, where: 0x0 is RCWSR12, 0x4 is RCWSR13, 0x8 is RCWSR14. An offset of 0x3 is not one of them and is not even aligned for the declared 32 bit register width. It is the only node in this pinmux that does not use 0x0, 0x4 neither 0x8. The value is wrong too: IIC5_PMUX is RCWSR12[11:9] and it encodes 0b000 for IIC5, 0b001 for GPIO_1[25:24], 0b010 for SDHC1_CLK_SYNC_OUT/IN, 0b011 for {IIC5_SCL,IIC5_SDA} = {SPI3_SOUT,SPI3_SIN}. This node selects the last of those, so it needs 0x3, not the 0x2, which is the value of the neighbouring sdhc1 clock sync node it was copied from. Fixes: 284ad7064aaa ("arm64: dts: lx2160a: complete pinmux for rcwsr12 configuration word") Reviewed-by: Josua Mayer Signed-off-by: Vincent Jardin Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi index d9d4500a4051..bccf2d673023 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx216x.dtsi @@ -1602,7 +1602,7 @@ }; dspi2_miso_mosi_pins: iic5-spi3-pins { - pinctrl-single,bits = <0x3 (0x2 << 9) (0x7 << 9)>; + pinctrl-single,bits = <0x0 (0x3 << 9) (0x7 << 9)>; }; i2c5_pins: iic6-i2c-pins { -- cgit v1.2.3 From cf08ef6995204752d8423226f3588c76c6403996 Mon Sep 17 00:00:00 2001 From: Franz Schnyder Date: Fri, 21 Aug 2026 16:58:58 +0200 Subject: arm64: dts: apalis-imx8: Add USB HSIC support Enable the USB HSIC host path on Apalis iMX8 modules. Signed-off-by: Franz Schnyder Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi | 6 +++++- .../arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi | 6 +++++- .../arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi | 6 +++++- arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi | 16 +++++++++++++++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi index 6f5af37ba9af..1d4e92f674f8 100644 --- a/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-apalis-eval.dtsi @@ -133,7 +133,11 @@ status = "okay"; }; -/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +&usbh1 { + vbus-supply = <®_usb_host_vbus>; + status = "okay"; +}; /* Apalis USBO1 */ &usbotg1 { diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi index 93f485140b20..68fb2eb8c7e6 100644 --- a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.1.dtsi @@ -222,7 +222,11 @@ status = "okay"; }; -/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +&usbh1 { + vbus-supply = <®_usb_host_vbus>; + status = "okay"; +}; /* Apalis USBO1 */ &usbotg1 { diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi index 5c86bcee55fb..baf09624fb27 100644 --- a/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi @@ -271,7 +271,11 @@ status = "okay"; }; -/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +&usbh1 { + vbus-supply = <®_usb_host_vbus>; + status = "okay"; +}; /* Apalis USBO1 */ &usbotg1 { diff --git a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi index 681f24810d52..64604f91d567 100644 --- a/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi @@ -870,7 +870,21 @@ status = "okay"; }; -/* TODO: Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +/* Apalis USBH2, Apalis USBH3 and on-module Wi-Fi via on-module HSIC Hub */ +&usbh1 { + pinctrl-names = "idle", "active"; + pinctrl-0 = <&pinctrl_usb_hsic_idle>; + pinctrl-1 = <&pinctrl_usb_hsic_active>; + adp-disable; + disable-over-current; + hnp-disable; + srp-disable; + status = "disabled"; +}; + +&usbphynop2 { + status = "okay"; +}; /* Apalis USBH4 */ &usb3_phy { -- cgit v1.2.3 From 3dc0aa7dc7de2d927657699219ae4751a72ebed6 Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Thu, 27 Aug 2026 09:57:54 +0200 Subject: arm64: dts: imx8mp-phyboard-pollux: add PEB-WLBT-07 expansion board Add support for PEB-WLBT-07 which is an expansion board that provides WiFi 6 and Bluetooth 5.4 LE functionality. It features the u-blox MAYA-W2 module with the NXP IW612 chipset. Signed-off-by: Primoz Fiser Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 3 + .../imx8mp-phyboard-pollux-peb-wlbt-07.dtso | 76 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-wlbt-07.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 51b217a11fad..44151be10233 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -668,6 +668,8 @@ imx8mp-phyboard-pollux-peb-av-10-etml1010g3dra-dtbs += imx8mp-phyboard-pollux-rd imx8mp-phyboard-pollux-peb-av-10-etml1010g3dra.dtbo imx8mp-phyboard-pollux-peb-av-10-ph128800t006-dtbs += imx8mp-phyboard-pollux-rdk.dtb \ imx8mp-phyboard-pollux-peb-av-10-ph128800t006.dtbo +imx8mp-phyboard-pollux-peb-wlbt-07-dtbs += imx8mp-phyboard-pollux-rdk.dtb \ + imx8mp-phyboard-pollux-peb-wlbt-07.dtbo imx8mp-phyboard-pollux-ph128800t006-dtbs += imx8mp-phyboard-pollux-rdk.dtb \ imx8mp-phyboard-pollux-ph128800t006.dtbo imx8mp-phyboard-pollux-rdk-no-eth-dtbs += imx8mp-phyboard-pollux-rdk.dtb imx8mp-phycore-no-eth.dtbo @@ -677,6 +679,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-etml1010g3dra.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-peb-av-10.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-peb-av-10-etml1010g3dra.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-peb-av-10-ph128800t006.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-peb-wlbt-07.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-ph128800t006.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk-no-eth.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-wlbt.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-wlbt-07.dtso b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-wlbt-07.dtso new file mode 100644 index 000000000000..008b6f9f46e5 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-phyboard-pollux-peb-wlbt-07.dtso @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* +* Copyright (C) 2026 PHYTEC Messtechnik GmbH +*/ + +#include +#include +#include +#include "imx8mp-pinfunc.h" + +/dts-v1/; +/plugin/; + +&{/} { + usdhc1_pwrseq: pwr-seq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>; + }; +}; + +&iomuxc { + pinctrl_uart3: uart3grp { + fsl,pins = < + MX8MP_IOMUXC_SD1_RESET_B__UART3_DCE_RTS 0x140 /* RTS */ + MX8MP_IOMUXC_SD1_STROBE__UART3_DCE_CTS 0x140 /* CTS */ + MX8MP_IOMUXC_UART3_RXD__UART3_DCE_RX 0x140 /* RX */ + MX8MP_IOMUXC_UART3_TXD__UART3_DCE_TX 0x140 /* TX */ + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MP_IOMUXC_SD1_CLK__USDHC1_CLK 0x190 /* SDIO_CLK */ + MX8MP_IOMUXC_SD1_CMD__USDHC1_CMD 0x1d0 /* SDIO_CMD */ + MX8MP_IOMUXC_SD1_DATA0__USDHC1_DATA0 0x1d0 /* SDIO_D0 */ + MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0 /* SDIO_D1 */ + MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0 /* SDIO_D2 */ + MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0 /* SDIO_D3 */ + >; + }; + + pinctrl_wlbt: wlbtgrp { + fsl,pins = < + MX8MP_IOMUXC_SPDIF_EXT_CLK__GPIO5_IO05 0x106 /* WAKE_DEV */ + MX8MP_IOMUXC_SD1_DATA5__GPIO2_IO07 0x106 /* PDn */ + MX8MP_IOMUXC_SD1_DATA7__GPIO2_IO09 0x106 /* WAKE_HOST */ + >; + }; +}; + +&uart3 { + assigned-clocks = <&clk IMX8MP_CLK_UART3>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>; + pinctrl-0 = <&pinctrl_uart3>; + pinctrl-names = "default"; + uart-has-rtscts; + status = "okay"; + + bluetooth { + compatible = "nxp,88w8987-bt"; + vcc-supply = <®_vcc_3v3_sw>; + }; +}; + +&usdhc1 { + bus-width = <4>; + keep-power-in-suspend; + max-frequency = <50000000>; + mmc-pwrseq = <&usdhc1_pwrseq>; + non-removable; + pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_wlbt>; + pinctrl-names = "default"; + vmmc-supply = <®_vcc_3v3_sw>; + wakeup-source; + status = "okay"; +}; -- cgit v1.2.3 From 242757d109bd5c9b8fb7194fb4d44625be0b859a Mon Sep 17 00:00:00 2001 From: Yo'av Moshe Date: Sun, 30 Aug 2026 17:51:00 +0200 Subject: ARM: imx: Fix suspend/resume crash with Clang CFI The suspend code that runs from OCRAM is copied there with fncpy(), which does not copy the kCFI type hash preceding the function. With CONFIG_CFI=y the indirect call through imx6_suspend_in_ocram_fn therefore panics. Keep the call covered by CFI instead of exempting it: - Add SYM_TYPED_FUNC_START_ALIGNED(), a variant of SYM_TYPED_FUNC_START() that aligns the function entry rather than the type hash preceding it, and use it to declare imx6_suspend(): fncpy() requires the entry point of the function it copies to be 8-byte aligned. The macro lives in arch/arm/include/asm/linkage.h since the requirement comes from arm's fncpy(). - Add a cfi_type member at the end of struct imx6_cpu_pm_info, which directly precedes the OCRAM copy of the function. It fits in the struct's tail padding, so no sizes or offsets change. Fill it using cfi_get_func_hash(), putting the hash where the caller's CFI check expects it: four bytes before the function entry. Also mark ccm_base, suspend_ocram_base and imx6_suspend_in_ocram_fn as __ro_after_init: they are only written during __init, and the function pointer in particular should not be writable afterwards. Suggested-by: Nick Desaulniers Cc: stable@vger.kernel.org Signed-off-by: Yo'av Moshe Reviewed-by: Nick Desaulniers Reviewed-by: Sami Tolvanen Signed-off-by: Frank Li --- arch/arm/include/asm/linkage.h | 29 +++++++++++++++++++++++++++++ arch/arm/mach-imx/pm-imx6.c | 26 +++++++++++++++++++++++--- arch/arm/mach-imx/suspend-imx6.S | 6 ++++-- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/linkage.h b/arch/arm/include/asm/linkage.h index c4670694ada7..bba992f5d7a8 100644 --- a/arch/arm/include/asm/linkage.h +++ b/arch/arm/include/asm/linkage.h @@ -9,4 +9,33 @@ .type name, %function; \ END(name) +#ifdef __ASSEMBLY__ + +/* + * Variants of SYM_TYPED_START/SYM_TYPED_FUNC_START that align the + * function entry itself instead of the kCFI type hash preceding it, + * for functions whose entry point must meet an alignment requirement, + * such as the 8-byte alignment fncpy() demands of its source. + */ +#ifdef CONFIG_CFI + +#define SYM_TYPED_START_ALIGNED(name, linkage, align) \ + linkage(name) ASM_NL \ + .balign align ASM_NL \ + .fill (align) - 4, 1, 0 ASM_NL \ + __CFI_TYPE(name) ASM_NL \ + name: + +#else /* CONFIG_CFI */ + +#define SYM_TYPED_START_ALIGNED(name, linkage, align) \ + SYM_START(name, linkage, .balign align) + +#endif /* CONFIG_CFI */ + +#define SYM_TYPED_FUNC_START_ALIGNED(name, align) \ + SYM_TYPED_START_ALIGNED(name, SYM_L_GLOBAL, align) + +#endif /* __ASSEMBLY__ */ + #endif diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index a671ca498f88..3c73e2cdb8ce 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -4,6 +4,8 @@ * Copyright 2011 Linaro Ltd. */ +#include +#include #include #include #include @@ -18,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -61,9 +64,9 @@ #define MX6Q_SUSPEND_OCRAM_SIZE 0x1000 #define MX6_MAX_MMDC_IO_NUM 33 -static void __iomem *ccm_base; -static void __iomem *suspend_ocram_base; -static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase); +static void __iomem *ccm_base __ro_after_init; +static void __iomem *suspend_ocram_base __ro_after_init; +static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase) __ro_after_init; /* * suspend ocram space layout: @@ -229,8 +232,18 @@ struct imx6_cpu_pm_info { struct imx6_pm_base l2_base; u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */ u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */ + u32 cfi_type; /* kCFI type hash of imx6_suspend() */ } __aligned(8); +/* + * The ocram copy of imx6_suspend() starts right after struct imx6_cpu_pm_info, + * and the CFI check on the indirect call reads the kCFI type hash from the + * four bytes preceding the function entry, so cfi_type must occupy the last + * four bytes of the struct, i.e. fit into its tail padding. + */ +static_assert(offsetofend(struct imx6_cpu_pm_info, cfi_type) == + sizeof(struct imx6_cpu_pm_info)); + void imx6_set_int_mem_clk_lpm(bool enable) { u32 val = readl_relaxed(ccm_base + CGPR); @@ -568,6 +581,13 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) mmdc_offset_array[i]); } + /* + * Mask out the Thumb bit, as cfi_get_func_hash() expects the + * function's actual start address. Returns 0 if CONFIG_CFI=n. + */ + pm_info->cfi_type = + cfi_get_func_hash((void *)((uintptr_t)&imx6_suspend & ~1UL)); + imx6_suspend_in_ocram_fn = fncpy( suspend_ocram_base + sizeof(*pm_info), &imx6_suspend, diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S index 63ccc2d0e920..95d5f723ea0e 100644 --- a/arch/arm/mach-imx/suspend-imx6.S +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -3,6 +3,7 @@ * Copyright 2014 Freescale Semiconductor, Inc. */ +#include #include #include #include @@ -148,7 +149,8 @@ .endm -ENTRY(imx6_suspend) +/* fncpy() requires an 8-byte-aligned entry; see arch/arm/include/asm/fncpy.h */ +SYM_TYPED_FUNC_START_ALIGNED(imx6_suspend, 8) ldr r1, [r0, #PM_INFO_PBASE_OFFSET] ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET] ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET] @@ -329,4 +331,4 @@ resume: resume_mmdc ret lr -ENDPROC(imx6_suspend) +SYM_FUNC_END(imx6_suspend) -- cgit v1.2.3 From 26835cf70bbb6207214af55495ea8bed9ea96775 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 25 Aug 2026 16:26:40 +0200 Subject: arm64: dts: imx8mn: Add ifm VHIP4 EvalBoard configuration EEPROM layout DTOs Add DT overlays which describe configuration EEPROM VHIP section, for VHIP section v1.0.0.0, v1.1.0.0, v2.0.0.0, used on ifm VHIP4 EvalBoard . With the DTO applied, the VHIP section fields become accessible via sysfs nvmem interface. The entire EEPROM is accessible via the nvmem interface as well. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 17 +++- .../imx8mn-vhip4-overlay-eeprom-1000.dtso | 103 ++++++++++++++++++++ .../imx8mn-vhip4-overlay-eeprom-1100.dtso | 103 ++++++++++++++++++++ .../imx8mn-vhip4-overlay-eeprom-2000.dtso | 107 +++++++++++++++++++++ 4 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1000.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1100.dtso create mode 100644 arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-2000.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 44151be10233..984642146dd9 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -319,15 +319,25 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mn-var-som-symphony.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mn-var-som-symphony-legacy.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mn-venice-gw7902.dtb +imx8mn-vhip4-evalboard-v1-overlay-eeprom-1000-dtbs := imx8mn-vhip4-evalboard-v1.dtb \ + imx8mn-vhip4-overlay-eeprom-1000.dtbo +imx8mn-vhip4-evalboard-v1-overlay-eeprom-1100-dtbs := imx8mn-vhip4-evalboard-v1.dtb \ + imx8mn-vhip4-overlay-eeprom-1100.dtbo imx8mn-vhip4-evalboard-v1-overlay-ksz8794-dtbs := imx8mn-vhip4-evalboard-v1.dtb \ imx8mn-vhip4-evalboard-v1-overlay-ksz8794.dtbo imx8mn-vhip4-evalboard-v1-overlay-ksz9031-dtbs := imx8mn-vhip4-evalboard-v1.dtb \ imx8mn-vhip4-evalboard-v1-overlay-ksz9031.dtbo imx8mn-vhip4-evalboard-v2-overlay-adin1300-dtbs := imx8mn-vhip4-evalboard-v2.dtb \ imx8mn-vhip4-evalboard-v2-overlay-adin1300.dtbo +imx8mn-vhip4-evalboard-v2-overlay-eeprom-1100-dtbs := imx8mn-vhip4-evalboard-v2.dtb \ + imx8mn-vhip4-overlay-eeprom-1100.dtbo +imx8mn-vhip4-evalboard-v2-overlay-eeprom-2000-dtbs := imx8mn-vhip4-evalboard-v2.dtb \ + imx8mn-vhip4-overlay-eeprom-2000.dtbo imx8mn-vhip4-evalboard-v2-overlay-ksz8794-dtbs := imx8mn-vhip4-evalboard-v2.dtb \ imx8mn-vhip4-evalboard-v2-overlay-ksz8794.dtbo dtb-$(CONFIG_ARCH_MXC) += imx8mn-vhip4-evalboard-v1.dtb \ + imx8mn-vhip4-evalboard-v1-overlay-eeprom-1000.dtb \ + imx8mn-vhip4-evalboard-v1-overlay-eeprom-1100.dtb \ imx8mn-vhip4-evalboard-v1-overlay-ksz8794.dtb \ imx8mn-vhip4-evalboard-v1-overlay-ksz8794.dtbo \ imx8mn-vhip4-evalboard-v1-overlay-ksz9031.dtb \ @@ -335,8 +345,13 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mn-vhip4-evalboard-v1.dtb \ imx8mn-vhip4-evalboard-v2.dtb \ imx8mn-vhip4-evalboard-v2-overlay-adin1300.dtb \ imx8mn-vhip4-evalboard-v2-overlay-adin1300.dtbo \ + imx8mn-vhip4-evalboard-v2-overlay-eeprom-1100.dtb \ + imx8mn-vhip4-evalboard-v2-overlay-eeprom-2000.dtb \ imx8mn-vhip4-evalboard-v2-overlay-ksz8794.dtb \ - imx8mn-vhip4-evalboard-v2-overlay-ksz8794.dtbo + imx8mn-vhip4-evalboard-v2-overlay-ksz8794.dtbo \ + imx8mn-vhip4-overlay-eeprom-1000.dtbo \ + imx8mn-vhip4-overlay-eeprom-1100.dtbo \ + imx8mn-vhip4-overlay-eeprom-2000.dtbo imx8mn-tqma8mqnl-mba8mx-lvds-g133han01-dtbs += imx8mn-tqma8mqnl-mba8mx.dtb imx8mm-tqma8mqml-mba8mx-lvds-g133han01.dtbo imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33-dtbs += imx8mn-tqma8mqnl-mba8mx.dtb imx8mn-tqma8mqnl-mba8mx-lvds-tm070jvhg33.dtbo diff --git a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1000.dtso b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1000.dtso new file mode 100644 index 000000000000..da3a40a310fa --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1000.dtso @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +&cfg_eeprom { + cfg_eeprom_layout: nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + vhip-signature@0 { + reg = <0x0 0x4>; + }; + + vhip-version@4 { + reg = <0x4 0x4>; + }; + + vhip-size@8 { + reg = <0x8 0x4>; + }; + + device-serial@c { + reg = <0xc 0x10>; + }; + + order-number@1c { + reg = <0x1c 0x20>; + }; + + article-name@3c { + reg = <0x3c 0x20>; + }; + + article-rev@5c { + reg = <0x5c 0x4>; + }; + + hardware-rev@60 { + reg = <0x60 0x4>; + }; + + product-type@64 { + reg = <0x64 0x20>; + }; + + software-compatibility@84 { + reg = <0x84 0x4>; + }; + + manufacturing-date@88 { + reg = <0x88 0x20>; + }; + + production-order-number@a8 { + reg = <0xa8 0x20>; + }; + + /* Each MAC address is padded to 8 Bytes */ + cfg_eeprom_mac1: mac-address-1@c8 { + reg = <0xc8 0x8>; + }; + + cfg_eeprom_mac2: mac-address-2@d0 { + reg = <0xd0 0x8>; + }; + + cfg_eeprom_mac3: mac-address-3@d8 { + reg = <0xd8 0x8>; + }; + + cfg_eeprom_mac4: mac-address-4@e0 { + reg = <0xe0 0x8>; + }; + + cfg_eeprom_mac5: mac-address-5@e8 { + reg = <0xe8 0x8>; + }; + + cfg_eeprom_mac6: mac-address-6@f0 { + reg = <0xf0 0x8>; + }; + + cfg_eeprom_mac7: mac-address-7@f8 { + reg = <0xf8 0x8>; + }; + + cfg_eeprom_mac8: mac-address-8@100 { + reg = <0x100 0x8>; + }; + + next-block-offset@108 { + reg = <0x108 0x4>; + }; + + section-crc@10c { + reg = <0x10c 0x4>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1100.dtso b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1100.dtso new file mode 100644 index 000000000000..30df55621b7b --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-1100.dtso @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +&cfg_eeprom { + cfg_eeprom_layout: nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + vhip-signature@0 { + reg = <0x0 0x4>; + }; + + vhip-version@4 { + reg = <0x4 0x4>; + }; + + vhip-size@8 { + reg = <0x8 0x4>; + }; + + device-serial@c { + reg = <0xc 0x10>; + }; + + order-number@1c { + reg = <0x1c 0x20>; + }; + + article-name@3c { + reg = <0x3c 0x40>; + }; + + article-rev@7c { + reg = <0x7c 0x4>; + }; + + hardware-rev@80 { + reg = <0x80 0x4>; + }; + + product-type@84 { + reg = <0x84 0x20>; + }; + + software-compatibility@a4 { + reg = <0xa4 0x4>; + }; + + manufacturing-date@a8 { + reg = <0xa8 0x20>; + }; + + production-order-number@c8 { + reg = <0xc8 0x20>; + }; + + /* Each MAC address is padded to 8 Bytes */ + cfg_eeprom_mac1: mac-address-1@e8 { + reg = <0xe8 0x8>; + }; + + cfg_eeprom_mac2: mac-address-2@f0 { + reg = <0xf0 0x8>; + }; + + cfg_eeprom_mac3: mac-address-3@f8 { + reg = <0xf8 0x8>; + }; + + cfg_eeprom_mac4: mac-address-4@100 { + reg = <0x100 0x8>; + }; + + cfg_eeprom_mac5: mac-address-5@108 { + reg = <0x108 0x8>; + }; + + cfg_eeprom_mac6: mac-address-6@110 { + reg = <0x110 0x8>; + }; + + cfg_eeprom_mac7: mac-address-7@118 { + reg = <0x118 0x8>; + }; + + cfg_eeprom_mac8: mac-address-8@120 { + reg = <0x120 0x8>; + }; + + next-block-offset@128 { + reg = <0x128 0x4>; + }; + + section-crc@12c { + reg = <0x12c 0x4>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-2000.dtso b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-2000.dtso new file mode 100644 index 000000000000..a2ca7ee8a2d2 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mn-vhip4-overlay-eeprom-2000.dtso @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2026 Marek Vasut + */ +/dts-v1/; +/plugin/; + +&cfg_eeprom { + cfg_eeprom_layout: nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + vhip-signature@0 { + reg = <0x0 0x4>; + }; + + vhip-version@4 { + reg = <0x4 0x4>; + }; + + vhip-size@8 { + reg = <0x8 0x4>; + }; + + section-data-crc@c { + reg = <0xc 0x4>; + }; + + next-block-offset@10 { + reg = <0x10 0x4>; + }; + + section-header-crc@14 { + reg = <0x14 0x4>; + }; + + device-serial@18 { + reg = <0x18 0x10>; + }; + + order-number@28 { + reg = <0x28 0x20>; + }; + + article-name@48 { + reg = <0x48 0x40>; + }; + + article-rev@88 { + reg = <0x88 0x4>; + }; + + hardware-rev@8c { + reg = <0x8c 0x4>; + }; + + product-type@90 { + reg = <0x90 0x20>; + }; + + software-compatibility@b0 { + reg = <0xb0 0x4>; + }; + + manufacturing-date@b4 { + reg = <0xb4 0x20>; + }; + + production-order-number@d4 { + reg = <0xd4 0x20>; + }; + + /* Each MAC address is padded to 8 Bytes */ + cfg_eeprom_mac1: mac-address-1@f4 { + reg = <0xf4 0x8>; + }; + + cfg_eeprom_mac2: mac-address-2@fc { + reg = <0xfc 0x8>; + }; + + cfg_eeprom_mac3: mac-address-3@104 { + reg = <0x104 0x8>; + }; + + cfg_eeprom_mac4: mac-address-4@10c { + reg = <0x10c 0x8>; + }; + + cfg_eeprom_mac5: mac-address-5@114 { + reg = <0x114 0x8>; + }; + + cfg_eeprom_mac6: mac-address-6@11c { + reg = <0x11c 0x8>; + }; + + cfg_eeprom_mac7: mac-address-7@124 { + reg = <0x124 0x8>; + }; + + cfg_eeprom_mac8: mac-address-8@12c { + reg = <0x12c 0x8>; + }; + }; +}; -- cgit v1.2.3 From 8392af7be78d0cdc5f1ec6c9a53d424b32642403 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 15 Aug 2026 17:32:00 +0200 Subject: ARM: imx6q: remove KSZ9021 PHY fixup 477fce49aef4 ("arm/imx6q-sabrelite: add enet phy ksz9021rn fixup") added this PHY fixup in 2011. In 2013 954c396756e3 ("net/phy: micrel: Add OF configuration support for ksz9021") added support for configuring pad skew parameters via OF, removing the need for the board-level fixup. Note: In 2013 14078291d89b ("ARM: i.MX6: call ksz9021 phy fixup for all i.MX6 boards") extended usage of the fixup to nitrogen6x and titanium. nitrogen6x configures the PHY properly via OF, and titanium has no mainline Linux support. From u-boot titanium support was removed in 2021. Signed-off-by: Heiner Kallweit Signed-off-by: Frank Li --- arch/arm/mach-imx/mach-imx6q.c | 30 ------------------------------ include/linux/micrel_phy.h | 5 ----- 2 files changed, 35 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 7f6200925752..58f53fba202f 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -20,26 +20,6 @@ #include "cpuidle.h" #include "hardware.h" -/* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */ -static int ksz9021rn_phy_fixup(struct phy_device *phydev) -{ - if (IS_BUILTIN(CONFIG_PHYLIB)) { - /* min rx data delay */ - phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL, - 0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW); - phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0x0000); - - /* max rx/tx clock delay, min rx/tx control delay */ - phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL, - 0x8000 | MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW); - phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0xf0f0); - phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL, - MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW); - } - - return 0; -} - /* * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High * as they are used for slots1-7 PERST# @@ -68,14 +48,6 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup); -static void __init imx6q_enet_phy_init(void) -{ - if (IS_BUILTIN(CONFIG_PHYLIB)) { - phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, - ksz9021rn_phy_fixup); - } -} - static void __init imx6q_1588_init(void) { struct device_node *np; @@ -179,8 +151,6 @@ static void __init imx6q_init_machine(void) imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q", imx_get_soc_revision()); - imx6q_enet_phy_init(); - of_platform_default_populate(NULL, NULL, NULL); imx_anatop_init(); diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index 9c6f9817383f..bb71b2510c2c 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -47,11 +47,6 @@ #define MICREL_PHY_FXEN BIT(1) #define MICREL_KSZ8_P1_ERRATA BIT(2) -#define MICREL_KSZ9021_EXTREG_CTRL 0xB -#define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC -#define MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW 0x104 -#define MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW 0x105 - /* Device specific MII_BMCR (Reg 0) bits */ /* 1 = HP Auto MDI/MDI-X mode, 0 = Microchip Auto MDI/MDI-X mode */ #define KSZ886X_BMCR_HP_MDIX BIT(5) -- cgit v1.2.3 From 2966ab5708e704d4ff4a15f8ade2ee2b33ac8bf7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:40:23 +0200 Subject: ARM: dts: nxp: imx: Replace spaces indentation with tabs Replace excessive spaces for aligning indentation into tabs. This will be reported by dt-style-check ("[mixed-indent-chars] too many space characters in indent (more than 7)"). Also two GPIO values should be really separate <> entries. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts | 2 +- arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts | 2 +- arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts | 2 +- arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi | 20 ++++++++++---------- arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi | 2 +- arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi | 10 +++++----- arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi | 10 +++++----- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts index 635c5a1e1fc7..e3496ea9643d 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-plym2m.dts @@ -155,7 +155,7 @@ touchscreen { compatible = "resistive-adc-touch"; io-channels = <&adc_ts 1>, <&adc_ts 3>, <&adc_ts 4>, - <&adc_ts 5>; + <&adc_ts 5>; io-channel-names = "y", "z1", "z2", "x"; touchscreen-min-pressure = <64687>; touchscreen-inverted-x; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts index 353f7097cb7e..09381dc980b2 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-prtvt7.dts @@ -288,7 +288,7 @@ touchscreen { compatible = "resistive-adc-touch"; io-channels = <&adc_ts 1>, <&adc_ts 3>, <&adc_ts 4>, - <&adc_ts 5>; + <&adc_ts 5>; io-channel-names = "y", "z1", "z2", "x"; touchscreen-min-pressure = <64687>; touchscreen-x-plate-ohms = <300>; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts index 18019a6bb3af..f874b2b11114 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-victgo.dts @@ -116,7 +116,7 @@ touchscreen { compatible = "resistive-adc-touch"; io-channels = <&adc_ts 1>, <&adc_ts 3>, <&adc_ts 4>, - <&adc_ts 5>; + <&adc_ts 5>; io-channel-names = "y", "z1", "z2", "x"; touchscreen-min-pressure = <64687>; touchscreen-inverted-y; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi index e9d5bbb43145..57f1583c74fb 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-gw560x.dtsi @@ -418,16 +418,16 @@ reg = <0x34>; interrupt-parent = <&gpio5>; interrupts = <11 IRQ_TYPE_EDGE_FALLING>; - linux,keymap = < MATRIX_KEY(0x00, 0x01, BTN_0) - MATRIX_KEY(0x00, 0x00, BTN_1) - MATRIX_KEY(0x01, 0x01, BTN_2) - MATRIX_KEY(0x01, 0x00, BTN_3) - MATRIX_KEY(0x02, 0x00, BTN_4) - MATRIX_KEY(0x00, 0x03, BTN_5) - MATRIX_KEY(0x00, 0x02, BTN_6) - MATRIX_KEY(0x01, 0x03, BTN_7) - MATRIX_KEY(0x01, 0x02, BTN_8) - MATRIX_KEY(0x02, 0x02, BTN_9) + linux,keymap = ; keypad,num-rows = <4>; keypad,num-columns = <4>; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi index e2631db798a8..27a73a3361ae 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-skov-cpu.dtsi @@ -28,7 +28,7 @@ iio-hwmon { compatible = "iio-hwmon"; io-channels = <&adc 0>, /* 24V */ - <&adc 1>; /* temperature */ + <&adc 1>; /* temperature */ }; leds { diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi index 9ff183e4e069..601733c3c2a9 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-zii-rdu2.dtsi @@ -22,8 +22,8 @@ #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mdio1>; - gpios = <&gpio6 5 GPIO_ACTIVE_HIGH - &gpio6 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio6 5 GPIO_ACTIVE_HIGH>, + <&gpio6 4 GPIO_ACTIVE_HIGH>; phy: ethernet-phy@0 { pinctrl-0 = <&pinctrl_rmii_phy_irq>; @@ -218,9 +218,9 @@ &clks { assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, - <&clks IMX6QDL_CLK_LDB_DI1_SEL>; + <&clks IMX6QDL_CLK_LDB_DI1_SEL>; assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>, - <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>; + <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>; }; &cpu0 { @@ -629,7 +629,7 @@ pinctrl-0 = <&pinctrl_ucs1002_pins>; reg = <0x32>; interrupts-extended = <&gpio5 2 IRQ_TYPE_EDGE_BOTH>, - <&gpio3 21 IRQ_TYPE_EDGE_FALLING>; + <&gpio3 21 IRQ_TYPE_EDGE_FALLING>; interrupt-names = "a_det", "alert"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi index 9438862b9927..86c4f7e010d0 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl.dtsi @@ -924,11 +924,11 @@ #power-domain-cells = <0>; power-supply = <®_pu>; clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>, - <&clks IMX6QDL_CLK_GPU3D_SHADER>, - <&clks IMX6QDL_CLK_GPU2D_CORE>, - <&clks IMX6QDL_CLK_GPU2D_AXI>, - <&clks IMX6QDL_CLK_OPENVG_AXI>, - <&clks IMX6QDL_CLK_VPU_AXI>; + <&clks IMX6QDL_CLK_GPU3D_SHADER>, + <&clks IMX6QDL_CLK_GPU2D_CORE>, + <&clks IMX6QDL_CLK_GPU2D_AXI>, + <&clks IMX6QDL_CLK_OPENVG_AXI>, + <&clks IMX6QDL_CLK_VPU_AXI>; }; }; }; -- cgit v1.2.3 From b7efad33a8d172a80a718804aebc1b2ab65802ba Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 25 Aug 2026 09:04:16 +0200 Subject: ARM: dts: mba6ulx: Add Ethernet PHY interrupt support With commit 417b0f8d08f87 ("gpio: pca953x: Add support for level-triggered interrupts") the GPIO expander gained support for level-low interrupts required for Ethernet PHYs Signed-off-by: Alexander Stein Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi index 1fda60d62ffe..6fedae7f06b1 100644 --- a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi @@ -215,6 +215,8 @@ clocks = <&clks IMX6UL_CLK_ENET_REF>; reg = <0>; max-speed = <100>; + interrupt-parent = <&expander_in0>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; }; ethphy1: ethernet-phy@1 { @@ -222,6 +224,8 @@ clocks = <&clks IMX6UL_CLK_ENET2_REF_125M>; reg = <1>; max-speed = <100>; + interrupt-parent = <&expander_in0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; }; }; }; @@ -261,18 +265,6 @@ gpio-controller; #gpio-cells = <2>; vcc-supply = <®_mba6ul_3v3>; - - enet1_int-hog { - gpio-hog; - gpios = <6 0>; - input; - }; - - enet2_int-hog { - gpio-hog; - gpios = <7 0>; - input; - }; }; expander_out1: gpio-expander@22 { -- cgit v1.2.3 From a637d2791eeb77912a7b48f30546ee5b6e16f5e9 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 25 Aug 2026 09:04:17 +0200 Subject: ARM: dts: mba6ulx: Add USB hub node Instead of handling the USB hub reset using a regulator, add a proper on-board USB hub device with reset-gpios set. Signed-off-by: Alexander Stein Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi index 6fedae7f06b1..fd05479bbffc 100644 --- a/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi +++ b/arch/arm/boot/dts/nxp/imx/mba6ulx.dtsi @@ -118,16 +118,6 @@ vin-supply = <®_mba6ul_3v3>; }; - reg_otg2vbus_5v0: regulator-otg2-vbus-5v0 { - compatible = "regulator-fixed"; - gpio = <&expander_out1 0 GPIO_ACTIVE_HIGH>; - enable-active-high; - regulator-name = "otg2-vbus-supply-5v0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <®_mpcie>; - }; - reserved-memory { #address-cells = <1>; #size-cells = <1>; @@ -369,10 +359,18 @@ /* 7-port usb hub */ /* id, pwr, oc pins not connected */ &usbotg2 { + #address-cells = <1>; + #size-cells = <0>; disable-over-current; - vbus-supply = <®_otg2vbus_5v0>; dr_mode = "host"; status = "okay"; + + hub_2_0: hub@1 { + compatible = "usb424,2517"; + reg = <1>; + reset-gpios = <&expander_out1 0 GPIO_ACTIVE_LOW>; + vdd-supply = <®_mba6ul_3v3>; + }; }; &usdhc1 { -- cgit v1.2.3 From 1e2a3d4a57fda613cd5127da8286183115a6b2d6 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:04 +0900 Subject: arm64: dts: imx91_93_common: Add clock and sound-dai-cells properties for MQS The "mclk" clock provides the MQS oversampling clock, and #sound-dai-cells describes the node as an ASoC DAI provider. Both are fixed SoC integration properties rather than board specific, so add them here in the common dtsi instead of duplicating them in each board dts. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts | 2 -- arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts | 2 -- arch/arm64/boot/dts/freescale/imx91_93_common.dtsi | 6 ++++++ arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts | 2 -- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts index 62dc1dedfb0e..c6019d76b998 100644 --- a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts +++ b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts @@ -672,8 +672,6 @@ }; &mqs1 { - clocks = <&clk IMX93_CLK_MQS1_GATE>; - clock-names = "mclk"; pinctrl-0 = <&pinctrl_mqs1>; pinctrl-names = "default"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts index c25561574d3f..6144fa6f3706 100644 --- a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts @@ -468,8 +468,6 @@ }; &mqs1 { - clocks = <&clk IMX93_CLK_MQS1_GATE>; - clock-names = "mclk"; pinctrl-0 = <&pinctrl_mqs1>; pinctrl-names = "default"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi b/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi index a1a7e6a0571b..a68ffd04ee08 100644 --- a/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi +++ b/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi @@ -100,13 +100,19 @@ mqs1: mqs1 { compatible = "fsl,imx93-mqs"; + clocks = <&clk IMX93_CLK_MQS1_GATE>; + clock-names = "mclk"; gpr = <&aonmix_ns_gpr>; + #sound-dai-cells = <0>; status = "disabled"; }; mqs2: mqs2 { compatible = "fsl,imx93-mqs"; + clocks = <&clk IMX93_CLK_MQS2_GATE>; + clock-names = "mclk"; gpr = <&wakeupmix_gpr>; + #sound-dai-cells = <0>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts index 8034992a73c7..61be6b1c169a 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts @@ -51,8 +51,6 @@ &mqs1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mqs1>; - clocks = <&clk IMX93_CLK_MQS1_GATE>; - clock-names = "mclk"; status = "okay"; }; -- cgit v1.2.3 From 3d25b0671b1b6395d3f64f2895ddcd72d04a9275 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:05 +0900 Subject: arm64: dts: imx91-11x11-evk: Add board muxes to select between PDM and MQS1 PDM has pin conflict with MQS1. Add GPIO-controlled board muxes to route shared signals between PDM and MQS1. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts index 5716febb5a50..4d1ada6a3942 100644 --- a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts @@ -41,6 +41,25 @@ stdout-path = &lpuart1; }; + pdm_mqs1_mux: mux-controller-0 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&adp5585 2 GPIO_ACTIVE_HIGH>; + }; + + pinctrl-gpiomux { + compatible = "pinctrl-multiplexer"; + + mqs1_fun: mqs1-grp { + mux-states = <&pdm_mqs1_mux 1>; + }; + + pdm_fun: pdm-grp { + mux-states = <&pdm_mqs1_mux 0>; + }; + }; + reg_vref_1v8: regulator-adc-vref { compatible = "regulator-fixed"; regulator-max-microvolt = <1800000>; @@ -484,7 +503,7 @@ &micfil { pinctrl-names = "default", "sleep"; - pinctrl-0 = <&pinctrl_pdm>; + pinctrl-0 = <&pinctrl_pdm>, <&pdm_fun>; pinctrl-1 = <&pinctrl_pdm_sleep>; assigned-clocks = <&clk IMX93_CLK_PDM>; assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; -- cgit v1.2.3 From fb33393964e4fbc4e3da2e0543830a17e2519d02 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:06 +0900 Subject: arm64: dts: imx91-11x11-evk: Add MQS1 pinmux, clocks and mark conflicting devices MQS1 shares pins with PDM and its sound card conflicts with the BT SCO card. Add the MQS1 pinctrl group and label the conflicting device and card so the shared imx9-mqs overlay can disable them. The overlay and its Makefile rule are added in a later patch. Update SAI1 clock assignments to provide the MQS MCLK source. Also describe the MQS output amplifier using the simple-audio-amplifier. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts | 33 +++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts index 4d1ada6a3942..6ccb942786c3 100644 --- a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts @@ -32,6 +32,12 @@ serial4 = &lpuart5; }; + amp_mqs1: audio-amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "MQS AMP"; + VCC-supply = <®_3p3v>; + }; + bt_sco_codec: bt-sco-codec { compatible = "linux,bt-sco"; #sound-dai-cells = <1>; @@ -60,6 +66,13 @@ }; }; + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_SW"; + }; + reg_vref_1v8: regulator-adc-vref { compatible = "regulator-fixed"; regulator-max-microvolt = <1800000>; @@ -145,7 +158,7 @@ "IN1R", "AMIC"; }; - sound-bt-sco { + mqs1_conflict_card: sound-bt-sco { compatible = "simple-audio-card"; simple-audio-card,name = "bt-sco-audio"; simple-audio-card,format = "dsp_a"; @@ -501,7 +514,7 @@ }; }; -&micfil { +mqs1_conflict_dev: &micfil { pinctrl-names = "default", "sleep"; pinctrl-0 = <&pinctrl_pdm>, <&pdm_fun>; pinctrl-1 = <&pinctrl_pdm_sleep>; @@ -511,10 +524,19 @@ status = "okay"; }; +&mqs1 { + pinctrl-0 = <&pinctrl_mqs1>, <&mqs1_fun>; + pinctrl-names = "default"; +}; + &sai1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&pinctrl_sai1>; pinctrl-1 = <&pinctrl_sai1_sleep>; + clocks = <&clk IMX93_CLK_SAI1_IPG>, <&clk IMX93_CLK_DUMMY>, + <&clk IMX93_CLK_SAI1_GATE>, <&clk IMX93_CLK_DUMMY>, + <&clk IMX93_CLK_DUMMY>, <&clk IMX93_CLK_AUDIO_PLL>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k"; assigned-clocks = <&clk IMX93_CLK_SAI1>; assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; assigned-clock-rates = <12288000>; @@ -720,6 +742,13 @@ >; }; + pinctrl_mqs1: mqs1grp { + fsl,pins = < + MX91_PAD_PDM_CLK__MQS1_LEFT 0x31e + MX91_PAD_PDM_BIT_STREAM0__MQS1_RIGHT 0x31e + >; + }; + pinctrl_pdm: pdmgrp { fsl,pins = < MX91_PAD_PDM_CLK__PDM_CLK 0x31e -- cgit v1.2.3 From 88f5a21dfd1ccbfdb1ac9bbea8e6603013e813eb Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:07 +0900 Subject: arm64: dts: imx93-11x11-evk: Add board muxes to select between PDM and MQS1 PDM has pin conflict with MQS1. Add GPIO-controlled board muxes to route shared signals between PDM and MQS1. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts index c6db9c85f2ac..4418fc6a0901 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts @@ -16,6 +16,25 @@ mmc2 = &usdhc3; }; + pdm_mqs1_mux: mux-controller-0 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&adp5585 2 GPIO_ACTIVE_HIGH>; + }; + + pinctrl-gpiomux { + compatible = "pinctrl-multiplexer"; + + mqs1_fun: mqs1-grp { + mux-states = <&pdm_mqs1_mux 1>; + }; + + pdm_fun: pdm-grp { + mux-states = <&pdm_mqs1_mux 0>; + }; + }; + reg_m2_pwr: regulator-m2-pwr { compatible = "regulator-fixed"; regulator-name = "M.2-power"; @@ -88,7 +107,7 @@ &micfil { pinctrl-names = "default", "sleep"; - pinctrl-0 = <&pinctrl_pdm>; + pinctrl-0 = <&pinctrl_pdm>, <&pdm_fun>; pinctrl-1 = <&pinctrl_pdm_sleep>; assigned-clocks = <&clk IMX93_CLK_PDM>; assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; -- cgit v1.2.3 From 3feae53c3fdd3f0860e63e511b8c1e8d3d58a0a3 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:08 +0900 Subject: arm64: dts: imx93-11x11-evk: Add MQS1 pinmux, clocks and mark conflicting devices MQS1 shares pins with PDM and its sound card conflicts with the BT SCO card. Add the MQS1 pinctrl group and label the conflicting device and card so the shared imx9-mqs overlay can disable them. The overlay and its Makefile rule are added in a later patch. Update SAI1 clock assignments to provide the MQS MCLK source. Also describe the MQS output amplifier using the simple-audio-amplifier. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts | 33 +++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts index 4418fc6a0901..d3312093f996 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk.dts @@ -16,6 +16,12 @@ mmc2 = &usdhc3; }; + amp_mqs1: audio-amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "MQS AMP"; + VCC-supply = <®_3p3v>; + }; + pdm_mqs1_mux: mux-controller-0 { compatible = "gpio-mux"; #mux-control-cells = <0>; @@ -35,6 +41,13 @@ }; }; + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_SW"; + }; + reg_m2_pwr: regulator-m2-pwr { compatible = "regulator-fixed"; regulator-name = "M.2-power"; @@ -71,7 +84,7 @@ #sound-dai-cells = <1>; }; - sound-bt-sco { + mqs1_conflict_card: sound-bt-sco { compatible = "simple-audio-card"; simple-audio-card,name = "bt-sco-audio"; simple-audio-card,format = "dsp_a"; @@ -105,7 +118,7 @@ }; }; -&micfil { +mqs1_conflict_dev: &micfil { pinctrl-names = "default", "sleep"; pinctrl-0 = <&pinctrl_pdm>, <&pdm_fun>; pinctrl-1 = <&pinctrl_pdm_sleep>; @@ -115,6 +128,11 @@ status = "okay"; }; +&mqs1 { + pinctrl-0 = <&pinctrl_mqs1>, <&mqs1_fun>; + pinctrl-names = "default"; +}; + &pcal6524 { m2-pcm-level-shifter-hog { gpio-hog; @@ -127,6 +145,10 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&pinctrl_sai1>; pinctrl-1 = <&pinctrl_sai1_sleep>; + clocks = <&clk IMX93_CLK_SAI1_IPG>, <&clk IMX93_CLK_DUMMY>, + <&clk IMX93_CLK_SAI1_GATE>, <&clk IMX93_CLK_DUMMY>, + <&clk IMX93_CLK_DUMMY>, <&clk IMX93_CLK_AUDIO_PLL>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k"; assigned-clocks = <&clk IMX93_CLK_SAI1>; assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; assigned-clock-rates = <12288000>; @@ -150,6 +172,13 @@ }; &iomuxc { + pinctrl_mqs1: mqs1grp { + fsl,pins = < + MX93_PAD_PDM_CLK__MQS1_LEFT 0x31e + MX93_PAD_PDM_BIT_STREAM0__MQS1_RIGHT 0x31e + >; + }; + pinctrl_pdm: pdmgrp { fsl,pins = < MX93_PAD_PDM_CLK__PDM_CLK 0x31e -- cgit v1.2.3 From ef9889f3421da84b46dddbfd93f05574390f8c2c Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:09 +0900 Subject: arm64: dts: imx93-14x14-evk: Add board muxes to select between FlexCAN1 and MQS1 FlexCAN1 has pin conflict with MQS1. Add GPIO-controlled board muxes to route shared signals between FlexCAN1 and MQS1. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts index ec78c03f4788..e35946bc3ddf 100644 --- a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts @@ -37,6 +37,25 @@ stdout-path = &lpuart1; }; + can1_mqs1_mux: mux-controller-0 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6524_2 2 GPIO_ACTIVE_HIGH>; + }; + + pinctrl-gpiomux { + compatible = "pinctrl-multiplexer"; + + can1_fun: can1-grp { + mux-states = <&can1_mqs1_mux 0>; + }; + + mqs1_fun: mqs1-grp { + mux-states = <&can1_mqs1_mux 1>; + }; + }; + reserved-memory { #address-cells = <2>; #size-cells = <2>; @@ -254,7 +273,7 @@ &flexcan1 { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_flexcan1>; + pinctrl-0 = <&pinctrl_flexcan1>, <&can1_fun>; xceiver-supply = <®_can1_stby>; status = "okay"; }; -- cgit v1.2.3 From e3503236b06af1ee92d5bbc298c6450aed4e06e3 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:10 +0900 Subject: arm64: dts: imx93-14x14-evk: Add MQS1 pinmux, clocks and mark conflicting devices MQS1 shares pins with FlexCAN1 and its sound card conflicts with the BT SCO card. Add the MQS1 pinctrl group and label the conflicting device and card so the shared imx9-mqs overlay can disable them. The overlay and its Makefile rule are added in a later patch. Update SAI1 clock assignments to provide the MQS MCLK source. Also describe the MQS output amplifier using the simple-audio-amplifier. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts | 34 +++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts index e35946bc3ddf..a025a08130f8 100644 --- a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts @@ -28,6 +28,13 @@ serial4 = &lpuart5; }; + amp_mqs1: audio-amplifier { + compatible = "simple-audio-amplifier"; + enable-gpios = <&pcal6524_2 1 GPIO_ACTIVE_HIGH>; + sound-name-prefix = "MQS AMP"; + VCC-supply = <®_5v>; + }; + bt_sco_codec: bt-sco-codec { compatible = "linux,bt-sco"; #sound-dai-cells = <1>; @@ -101,6 +108,13 @@ }; }; + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "+V5_SW"; + }; + reg_can1_stby: regulator-can1-stby { compatible = "regulator-fixed"; regulator-name = "can1-stby"; @@ -193,7 +207,7 @@ regulator-max-microvolt = <1800000>; }; - sound-bt-sco { + mqs1_conflict_card: sound-bt-sco { compatible = "simple-audio-card"; simple-audio-card,name = "bt-sco-audio"; simple-audio-card,format = "dsp_a"; @@ -271,7 +285,7 @@ }; }; -&flexcan1 { +mqs1_conflict_dev: &flexcan1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flexcan1>, <&can1_fun>; xceiver-supply = <®_can1_stby>; @@ -431,6 +445,11 @@ }; }; +&mqs1 { + pinctrl-0 = <&pinctrl_mqs1>, <&mqs1_fun>; + pinctrl-names = "default"; +}; + &mu1 { status = "okay"; }; @@ -442,6 +461,10 @@ &sai1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai1>; + clocks = <&clk IMX93_CLK_SAI1_IPG>, <&clk IMX93_CLK_DUMMY>, + <&clk IMX93_CLK_SAI1_GATE>, <&clk IMX93_CLK_DUMMY>, + <&clk IMX93_CLK_DUMMY>, <&clk IMX93_CLK_AUDIO_PLL>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k"; assigned-clocks = <&clk IMX93_CLK_SAI1>; assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; assigned-clock-rates = <12288000>; @@ -559,6 +582,13 @@ >; }; + pinctrl_mqs1: mqs1grp { + fsl,pins = < + MX93_PAD_PDM_CLK__MQS1_LEFT 0x31e + MX93_PAD_PDM_BIT_STREAM0__MQS1_RIGHT 0x31e + >; + }; + pinctrl_pcal6524: pcal6524grp { fsl,pins = < MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e -- cgit v1.2.3 From f33c249355b29b6f9582ef41b69093294b3d63cd Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:11 +0900 Subject: arm64: dts: imx94: Add clock and sound-dai-cells properties for MQS1 MQS1 MCLK input is driven from the respective SAI1 MCLK output, and sound-dai-cells describes the node as an ASoC DAI provider. Both are fixed SoC integration properties rather than board specific, so add them here in the common dtsi instead of duplicating them in each board dts. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx94.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx94.dtsi b/arch/arm64/boot/dts/freescale/imx94.dtsi index afaaf70417d2..020aa1da3315 100644 --- a/arch/arm64/boot/dts/freescale/imx94.dtsi +++ b/arch/arm64/boot/dts/freescale/imx94.dtsi @@ -131,6 +131,9 @@ mqs1: mqs1 { compatible = "fsl,imx943-aonmix-mqs"; + clocks = <&scmi_clk IMX94_CLK_SAI1>; + clock-names = "mclk"; + #sound-dai-cells = <0>; status = "disabled"; }; -- cgit v1.2.3 From 9e1ae128366b6f6b2aa4e13b2f7b62c6744ccfa5 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:12 +0900 Subject: arm64: dts: imx943-evk: Add board muxes to select between CAN1/PDM and MQS1/MIC CAN1 has pin conflict with PDM, and MQS1 has pin conflict with the MICFIL function. Replace static gpio-hog settings with GPIO-controlled board muxes using the pinctrl-multiplexer framework, so that the conflicting functions can be selected at runtime. Update the MICFIL node to select MICFIL function via PINCTRL. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx943-evk.dts | 49 ++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts index e1f6d64d3a3f..eca075f13749 100644 --- a/arch/arm64/boot/dts/freescale/imx943-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts @@ -38,6 +38,40 @@ #sound-dai-cells = <1>; }; + can1_pdm_mux: mux-controller-0 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6416_i2c6_u44 12 GPIO_ACTIVE_HIGH>; + }; + + mqs1_mic_mux: mux-controller-1 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6416_i2c3_u171 11 GPIO_ACTIVE_HIGH>; + }; + + pinctrl-gpiomux { + compatible = "pinctrl-multiplexer"; + + can1_fun: can1-grp { + mux-states = <&can1_pdm_mux 1>; + }; + + mic_fun: mic-grp { + mux-states = <&mqs1_mic_mux 0>; + }; + + mqs1_fun: mqs1-grp { + mux-states = <&mqs1_mic_mux 1>; + }; + + pdm_fun: pdm-grp { + mux-states = <&can1_pdm_mux 0>; + }; + }; + flexcan2_phy: can-phy0 { compatible = "nxp,tjr1443"; #phy-cells = <0>; @@ -556,12 +590,6 @@ gpio-hog; output-high; }; - - mqs-mic-sel-hog { - gpios = <11 GPIO_ACTIVE_HIGH>; - gpio-hog; - output-low; - }; }; }; @@ -672,13 +700,6 @@ #gpio-cells = <2>; gpio-controller; - /* pdm selection */ - can-pdm-sel-hog { - gpios = <12 GPIO_ACTIVE_HIGH>; - gpio-hog; - output-low; - }; - sai3-sel-hog { gpios = <11 GPIO_ACTIVE_HIGH>; gpio-hog; @@ -733,7 +754,7 @@ assigned-clock-rates = <3932160000>, <3612672000>, <393216000>, <361267200>, <49152000>; - pinctrl-0 = <&pinctrl_pdm>; + pinctrl-0 = <&pinctrl_pdm>, <&mic_fun>, <&pdm_fun>; pinctrl-names = "default"; status = "okay"; }; -- cgit v1.2.3 From f3a2aaa1dcbf46aa22a05f7d8ea823e2942b66b5 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:13 +0900 Subject: arm64: dts: imx943-evk: Add MQS1 pinmux, clocks and mark conflicting devices MQS1 shares pins with PDM and its sound card conflicts with the WM8962 sound card. Add the MQS1 pinctrl group and label the conflicting device and card so the shared imx9-mqs overlay can disable them. The overlay and its Makefile rule are added in a later patch. Update SAI1 clock assignments to provide the MQS MCLK source. Also describe the MQS output amplifier using the simple-audio-amplifier. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx943-evk.dts | 34 ++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx943-evk.dts b/arch/arm64/boot/dts/freescale/imx943-evk.dts index eca075f13749..39e819c536cc 100644 --- a/arch/arm64/boot/dts/freescale/imx943-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx943-evk.dts @@ -33,6 +33,12 @@ serial5 = &lpuart6; }; + amp_mqs1: audio-amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "MQS AMP"; + VCC-supply = <®_3p3v>; + }; + bt_sco_codec: bt-sco-codec { compatible = "linux,bt-sco"; #sound-dai-cells = <1>; @@ -142,6 +148,13 @@ }; }; + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_SW"; + }; + reg_m2_pwr: regulator-m2-pwr { compatible = "regulator-fixed"; regulator-name = "M.2-power"; @@ -362,7 +375,7 @@ }; }; - sound-wm8962 { + mqs1_conflict_card: sound-wm8962 { compatible = "fsl,imx-audio-wm8962"; audio-codec = <&wm8962>; audio-cpu = <&sai1>; @@ -743,7 +756,7 @@ }; }; -&micfil { +mqs1_conflict_dev: &micfil { assigned-clocks = <&scmi_clk IMX94_CLK_AUDIOPLL1_VCO>, <&scmi_clk IMX94_CLK_AUDIOPLL2_VCO>, <&scmi_clk IMX94_CLK_AUDIOPLL1>, @@ -759,6 +772,11 @@ status = "okay"; }; +&mqs1 { + pinctrl-0 = <&pinctrl_mqs1>, <&mqs1_fun>, <&pdm_fun>; + pinctrl-names = "default"; +}; + &mu11 { status = "okay"; }; @@ -805,6 +823,11 @@ }; &sai1 { + clocks = <&scmi_clk IMX94_CLK_BUSAON>, <&dummy>, + <&scmi_clk IMX94_CLK_SAI1>, <&dummy>, + <&dummy>, <&scmi_clk IMX94_CLK_AUDIOPLL1>, + <&scmi_clk IMX94_CLK_AUDIOPLL2>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k"; assigned-clocks = <&scmi_clk IMX94_CLK_AUDIOPLL1_VCO>, <&scmi_clk IMX94_CLK_AUDIOPLL2_VCO>, <&scmi_clk IMX94_CLK_AUDIOPLL1>, @@ -927,6 +950,13 @@ >; }; + pinctrl_mqs1: mqs1grp { + fsl,pins = < + IMX94_PAD_PDM_CLK__MQS1_LEFT 0x31e + IMX94_PAD_PDM_BIT_STREAM0__MQS1_RIGHT 0x31e + >; + }; + pinctrl_pcie0: pcie0grp { fsl,pins = < IMX94_PAD_GPIO_IO20__PCIE1_CLKREQ_B 0x4000031e -- cgit v1.2.3 From 117f69ab74f5b95206251fa50eb3779e4b254a18 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:14 +0900 Subject: arm64: dts: imx95: Add clock and sound-dai-cells properties for MQS1 MQS1 MCLK input is driven from the respective SAI1 MCLK output, and sound-dai-cells describes the node as an ASoC DAI provider. Both are fixed SoC integration properties rather than board specific, so add them here in the common dtsi instead of duplicating them in each board dts. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts | 2 -- arch/arm64/boot/dts/freescale/imx95-19x19-frdm-pro.dts | 2 -- arch/arm64/boot/dts/freescale/imx95.dtsi | 3 +++ 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts index 947d0c3748c5..ab1c1ccc9b6e 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts @@ -482,8 +482,6 @@ }; &mqs1 { - clocks = <&scmi_clk IMX95_CLK_SAI1>; - clock-names = "mclk"; pinctrl-0 = <&pinctrl_mqs1>; pinctrl-names = "default"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-frdm-pro.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-frdm-pro.dts index b87a26b0d7fc..1f62d729a5e7 100644 --- a/arch/arm64/boot/dts/freescale/imx95-19x19-frdm-pro.dts +++ b/arch/arm64/boot/dts/freescale/imx95-19x19-frdm-pro.dts @@ -450,8 +450,6 @@ }; &mqs1 { - clocks = <&scmi_clk IMX95_CLK_SAI1>; - clock-names = "mclk"; pinctrl-0 = <&pinctrl_mqs1>; pinctrl-names = "default"; status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi index 1cb8eb15e5c7..0f04d8bfcd88 100644 --- a/arch/arm64/boot/dts/freescale/imx95.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi @@ -439,6 +439,9 @@ mqs1: mqs-1 { compatible = "fsl,imx95-aonmix-mqs"; + clocks = <&scmi_clk IMX95_CLK_SAI1>; + clock-names = "mclk"; + #sound-dai-cells = <0>; status = "disabled"; }; -- cgit v1.2.3 From 810b7a200ce88136fa822c8e7258e0a4fe481a9e Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:15 +0900 Subject: arm64: dts: imx95-15x15-evk: Add board muxes to select between PDM and MQS1 PDM has pin conflict with MQS1. Add GPIO-controlled board muxes to route shared signals between PDM and MQS1. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts index 6aedcbbe915a..aaa2608793bf 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts @@ -114,6 +114,25 @@ silent-gpios = <&pcal6524 14 GPIO_ACTIVE_HIGH>; }; + pdm_mqs1_mux: mux-controller-0 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6524 20 GPIO_ACTIVE_HIGH>; + }; + + pinctrl-gpiomux { + compatible = "pinctrl-multiplexer"; + + pdm_fun: pdm-grp { + mux-states = <&pdm_mqs1_mux 0>; + }; + + mqs1_fun: mqs1-grp { + mux-states = <&pdm_mqs1_mux 1>; + }; + }; + reg_m2_pwr: regulator-m2-pwr { compatible = "regulator-fixed"; regulator-max-microvolt = <3300000>; @@ -488,7 +507,7 @@ assigned-clock-parents = <0>, <0>, <0>, <0>, <&scmi_clk IMX95_CLK_AUDIOPLL1>; assigned-clock-rates = <3932160000>, <3612672000>, <393216000>, <361267200>, <49152000>; #sound-dai-cells = <0>; - pinctrl-0 = <&pinctrl_pdm>; + pinctrl-0 = <&pinctrl_pdm>, <&pdm_fun>; pinctrl-names = "default"; status = "okay"; }; -- cgit v1.2.3 From 7956a20c9fbca9036f417fbc50e8e17ed92d09b4 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:16 +0900 Subject: arm64: dts: imx95-15x15-evk: Add MQS1 pinmux, clocks and mark conflicting devices MQS1 shares pins with PDM and its sound card conflicts with the BT SCO card. Add the MQS1 pinctrl group and label the conflicting device and card so the shared imx9-mqs overlay can disable them. The overlay and its Makefile rule are added in a later patch. Update SAI1 clock assignments to provide the MQS MCLK source. Also describe the MQS output amplifier using the simple-audio-amplifier. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts | 27 +++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts index aaa2608793bf..1ca6850a7365 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts @@ -48,6 +48,12 @@ serial4 = &lpuart5; }; + amp_mqs1: audio-amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "MQS AMP"; + VCC-supply = <®_3p3v>; + }; + bt_sco_codec: bt-sco-codec { compatible = "linux,bt-sco"; #sound-dai-cells = <1>; @@ -239,7 +245,7 @@ }; }; - sound-bt-sco { + mqs1_conflict_card: sound-bt-sco { compatible = "simple-audio-card"; simple-audio-card,bitclock-inversion; simple-audio-card,bitclock-master = <&btcpu>; @@ -498,7 +504,7 @@ }; }; -&micfil { +mqs1_conflict_dev: &micfil { assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>, <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>, <&scmi_clk IMX95_CLK_AUDIOPLL1>, @@ -512,6 +518,11 @@ status = "okay"; }; +&mqs1 { + pinctrl-0 = <&pinctrl_mqs1>, <&mqs1_fun>; + pinctrl-names = "default"; +}; + &mu7 { status = "okay"; }; @@ -592,6 +603,11 @@ }; &sai1 { + clocks = <&scmi_clk IMX95_CLK_BUSAON>, <&dummy>, + <&scmi_clk IMX95_CLK_SAI1>, <&dummy>, + <&dummy>, <&scmi_clk IMX95_CLK_AUDIOPLL1>, + <&scmi_clk IMX95_CLK_AUDIOPLL2>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k"; assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>, <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>, <&scmi_clk IMX95_CLK_AUDIOPLL1>, @@ -670,6 +686,13 @@ >; }; + pinctrl_mqs1: mqs1grp { + fsl,pins = < + IMX95_PAD_PDM_CLK__AONMIX_TOP_MQS1_LEFT 0x31e + IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_MQS1_RIGHT 0x31e + >; + }; + pinctrl_hp: hpgrp { fsl,pins = < IMX95_PAD_GPIO_IO21__GPIO2_IO_BIT21 0x31e -- cgit v1.2.3 From 2fa5c26d926322c7aed9c59740eb693da2335971 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:17 +0900 Subject: arm64: dts: imx952: Add AONMIX MQS device node Add DT node for AONMIX MQS (i.e. MQS1). Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx952.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx952.dtsi b/arch/arm64/boot/dts/freescale/imx952.dtsi index 887abb1c4784..8702e9fdd255 100644 --- a/arch/arm64/boot/dts/freescale/imx952.dtsi +++ b/arch/arm64/boot/dts/freescale/imx952.dtsi @@ -261,6 +261,14 @@ }; }; + mqs1: mqs1 { + compatible = "fsl,imx95-aonmix-mqs"; + clocks = <&scmi_clk IMX952_CLK_SAI1>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + status = "disabled"; + }; + gic: interrupt-controller@48000000 { compatible = "arm,gic-v3"; reg = <0 0x48000000 0 0x10000>, -- cgit v1.2.3 From 3bedcc4871b1e1e68ad755bae40567aa39183d50 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:18 +0900 Subject: arm64: dts: imx952-evk: Add board muxes to select between CAN1/PDM CAN1 has pin conflict with PDM. MQS1 requires an enable signal via a separate GPIO. Replace static gpio-hog settings with GPIO-controlled board muxes using the pinctrl-multiplexer framework, so that the conflicting functions can be selected at runtime. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx952-evk.dts | 50 ++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx952-evk.dts b/arch/arm64/boot/dts/freescale/imx952-evk.dts index 2224b90aafe9..e9d735dc2a51 100644 --- a/arch/arm64/boot/dts/freescale/imx952-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx952-evk.dts @@ -52,6 +52,40 @@ stdout-path = &lpuart1; }; + can1_pdm_mux: mux-controller-0 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6416 10 GPIO_ACTIVE_HIGH>; + }; + + mqs1_en_mux: mux-controller-1 { + compatible = "gpio-mux"; + #mux-control-cells = <0>; + #mux-state-cells = <1>; + mux-gpios = <&pcal6416 15 GPIO_ACTIVE_HIGH>; + }; + + pinctrl-gpiomux { + compatible = "pinctrl-multiplexer"; + + can1_fun: can1-grp { + mux-states = <&can1_pdm_mux 1>; + }; + + mqs1_disable: mqs1-disable-grp { + mux-states = <&mqs1_en_mux 0>; + }; + + mqs1_enable: mqs1-enable-grp { + mux-states = <&mqs1_en_mux 1>; + }; + + pdm_fun: pdm-grp { + mux-states = <&can1_pdm_mux 0>; + }; + }; + dmic: dmic { compatible = "dmic-codec"; #sound-dai-cells = <0>; @@ -284,7 +318,7 @@ /* pin conflict with PDM */ &flexcan1 { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_flexcan1>; + pinctrl-0 = <&pinctrl_flexcan1>, <&mqs1_disable>, <&can1_fun>; phys = <&flexcan1_phy>; status = "disabled"; }; @@ -387,18 +421,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcal6416>; vcc-supply = <®_3p3v>; - - pdm-can-sel-hog { - gpio-hog; - gpios = <10 GPIO_ACTIVE_HIGH>; - output-low; - }; - - mqs-en-hog { - gpio-hog; - gpios = <15 GPIO_ACTIVE_HIGH>; - output-low; - }; }; }; @@ -491,7 +513,7 @@ <&scmi_clk IMX952_CLK_AUDIOPLL1>; assigned-clock-rates = <3932160000>, <3612672000>, <393216000>, <361267200>, <49152000>; - pinctrl-0 = <&pinctrl_pdm>; + pinctrl-0 = <&pinctrl_pdm>, <&mqs1_disable>, <&pdm_fun>; pinctrl-1 = <&pinctrl_pdm_sleep>; pinctrl-names = "default", "sleep"; status = "okay"; -- cgit v1.2.3 From 8b6cf4986aa5436f3aa7f4ade6cd353e521669c6 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:19 +0900 Subject: arm64: dts: imx952-evk: Add MQS1 pinmux, clocks and mark conflicting devices MQS1 shares pins with PDM and its sound card conflicts with the BT SCO card. Add the MQS1 pinctrl group and label the conflicting device and card so the shared imx9-mqs overlay can disable them. The overlay and its Makefile rule are added in a later patch. Update SAI1 clock assignments to provide the MQS MCLK source. Also describe the MQS output amplifier using the simple-audio-amplifier. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx952-evk.dts | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx952-evk.dts b/arch/arm64/boot/dts/freescale/imx952-evk.dts index e9d735dc2a51..047dfde20718 100644 --- a/arch/arm64/boot/dts/freescale/imx952-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx952-evk.dts @@ -43,6 +43,12 @@ spi6 = &lpspi7; }; + amp_mqs1: audio-amplifier { + compatible = "simple-audio-amplifier"; + sound-name-prefix = "MQS AMP"; + VCC-supply = <®_3p3v>; + }; + bt_sco_codec: audio-codec-bt-sco { #sound-dai-cells = <1>; compatible = "linux,bt-sco"; @@ -231,7 +237,7 @@ <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>, <&m7_reserved>; }; - sound-bt-sco { + mqs1_conflict_card: sound-bt-sco { compatible = "simple-audio-card"; simple-audio-card,bitclock-inversion; simple-audio-card,bitclock-master = <&btcpu>; @@ -503,7 +509,7 @@ status = "okay"; }; -&micfil { +mqs1_conflict_dev: &micfil { assigned-clocks = <&scmi_clk IMX952_CLK_AUDIOPLL1_VCO>, <&scmi_clk IMX952_CLK_AUDIOPLL2_VCO>, <&scmi_clk IMX952_CLK_AUDIOPLL1>, @@ -519,11 +525,21 @@ status = "okay"; }; +&mqs1 { + pinctrl-0 = <&pinctrl_mqs1>, <&mqs1_enable>; + pinctrl-names = "default"; +}; + &mu7 { status = "okay"; }; &sai1 { + clocks = <&scmi_clk IMX952_CLK_BUSAON>, <&clk_dummy>, + <&scmi_clk IMX952_CLK_SAI1>, <&clk_dummy>, + <&clk_dummy>, <&scmi_clk IMX952_CLK_AUDIOPLL1>, + <&scmi_clk IMX952_CLK_AUDIOPLL2>; + clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k"; assigned-clocks = <&scmi_clk IMX952_CLK_AUDIOPLL1_VCO>, <&scmi_clk IMX952_CLK_AUDIOPLL2_VCO>, <&scmi_clk IMX952_CLK_AUDIOPLL1>, @@ -704,6 +720,13 @@ >; }; + pinctrl_mqs1: mqs1grp { + fsl,pins = < + IMX952_PAD_PDM_CLK__AONMIX_TOP_MQS1_LEFT 0x31e + IMX952_PAD_PDM_BIT_STREAM0__AONMIX_TOP_MQS1_RIGHT 0x31e + >; + }; + pinctrl_pcal6416: pcal6416grp { fsl,pins = < IMX952_PAD_GPIO_IO10__WAKEUPMIX_TOP_GPIO2_IO_10 0x31e -- cgit v1.2.3 From 153a8f4b71cee0e6ade27d7765de730af530653b Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 24 Aug 2026 11:20:20 +0900 Subject: arm64: dts: fsl: Add DT overlay to build MQS1 sound cards on i.MX9 platforms Add a common DT overlay to support MQS sound cards on i.MX9 platforms. MQS output pins are often shared with other devices, so the overlay routes SAI1 to MQS1 and disables the conflicting device and sound card. Attach the board amplifier as an aux device and add the DAPM routing from the MQS outputs to the amplifier inputs. Signed-off-by: Chancel Liu Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 12 ++++++ arch/arm64/boot/dts/freescale/imx9-mqs.dtso | 57 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx9-mqs.dtso diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 984642146dd9..7944e3b32513 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -847,6 +847,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx91-9x9-qsb-tianma-tm050rdh03.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-frdm.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-frdm-s.dtb +imx91-11x11-evk-mqs-dtbs += imx91-11x11-evk.dtb imx9-mqs.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-phyboard-segin.dtb imx91-9x9-qsb-can1-dtbs += imx91-9x9-qsb.dtb imx91-9x9-qsb-can1.dtbo @@ -879,6 +881,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk.dtb imx93-11x11-evk-dy1212w-4856-dtbs += imx93-11x11-evk.dtb imx93-11x11-evk-dy1212w-4856.dtbo dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk-dy1212w-4856.dtb +imx93-11x11-evk-mqs-dtbs += imx93-11x11-evk.dtb imx9-mqs.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-frdm.dtb @@ -886,6 +890,8 @@ imx93-11x11-frdm-pixpaper-dtbs += imx93-11x11-frdm.dtb imx93-11x11-frdm-pixpaper dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-frdm-pixpaper.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk.dtb +imx93-14x14-evk-mqs-dtbs += imx93-14x14-evk.dtb imx9-mqs.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-kontron-bl-osm-s.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-nash.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin.dtb @@ -938,6 +944,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx943-evk-pcie0-ep.dtb imx943-evk-pcie1-ep.dtb imx943-evk-sdwifi-dtbs := imx943-evk.dtb imx943-evk-sdwifi.dtbo dtb-$(CONFIG_ARCH_MXC) += imx943-evk-sdwifi.dtb +imx943-evk-mqs-dtbs += imx943-evk.dtb imx9-mqs.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx943-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-ab2.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk.dtb @@ -969,6 +977,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk-pcie.dtb imx95-15x15-evk-pcie0-ep-dtbs = imx95-15x15-evk-pcie.dtb imx-pcie0-ep.dtbo dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk-pcie0-ep.dtb +imx95-15x15-evk-mqs-dtbs += imx95-15x15-evk.dtb imx9-mqs.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-evk-mqs.dtb imx95-19x19-evk-pcie0-ep-dtbs += imx95-19x19-evk.dtb imx-pcie0-ep.dtbo imx95-19x19-evk-pcie1-ep-dtbs += imx95-19x19-evk.dtb imx-pcie1-ep.dtbo dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-pcie0-ep.dtb imx95-19x19-evk-pcie1-ep.dtb @@ -977,6 +987,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-libra-rdk-fpsc.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-verdin-evk.dtb dtb-$(CONFIG_ARCH_MXC) += imx952-evk.dtb +imx952-evk-mqs-dtbs += imx952-evk.dtb imx9-mqs.dtbo +dtb-$(CONFIG_ARCH_MXC) += imx952-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx952-frdm.dtb diff --git a/arch/arm64/boot/dts/freescale/imx9-mqs.dtso b/arch/arm64/boot/dts/freescale/imx9-mqs.dtso new file mode 100644 index 000000000000..bdb251299e52 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx9-mqs.dtso @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2026 NXP + */ + +/dts-v1/; +/plugin/; + +&{/} { + sound-mqs { + compatible = "audio-graph-card2"; + aux-devs = <&_mqs1>; + label = "mqs-audio"; + links = <&sai1_port1>; + routing = "MQS AMP INL", "MQS_L", + "MQS AMP INR", "MQS_R"; + }; +}; + +&mqs1_conflict_card { + status = "disabled"; +}; + +&mqs1_conflict_dev { + status = "disabled"; +}; + +&mqs1 { + status = "okay"; + + port { + mqs1_endpoint: endpoint { + remote-endpoint = <&sai1_endpoint1>; + }; + }; +}; + +&sai1 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + sai1_port1: port@1 { + reg = <1>; + playback-only; + + sai1_endpoint1: endpoint { + dai-format = "left_j"; + bitclock-master; + frame-master; + mclk-fs = <512>; + system-clock-direction-out; + remote-endpoint = <&mqs1_endpoint>; + }; + }; + }; +}; -- cgit v1.2.3 From 3d597df4760eae04914c52dedc55e1325f7e1e62 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 10 Aug 2026 21:06:03 +0300 Subject: ARM: dts: nxp: imx6qdl-pico: Replace clock-frequency in camera sensor node The clock-frequency for camera sensors has been deprecated in favour of the assigned-clocks and assigned-clock-rates properties since 'commit aa1826696a55 ("dt-bindings: media: Deprecate clock-frequency property for camera sensors")' in v6.18. The Linux kernel ov5645 driver has been handling the deprecated property as optional since the same kernel version. Replace the property in the device tree. There are no known users of the property outside of the Linux kernel. In particular, U-Boot doesn't operate the camera. Switching to the new bindings will therefore not introduce any breakage. Signed-off-by: Laurent Pinchart Reviewed-by: Mehdi Djait Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi index ca4cb986efbc..0cc05d084f9b 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-pico.dtsi @@ -233,7 +233,9 @@ pinctrl-0 = <&pinctrl_ov5645>; reg = <0x3c>; clocks = <&clks IMX6QDL_CLK_CKO2>; - clock-frequency = <24000000>; + assigned-clocks = <&clks IMX6QDL_CLK_CKO2>; + assigned-clock-rates = <24000000>; + vdddo-supply = <®_1p8v>; vdda-supply = <®_2p8v>; vddd-supply = <®_1p5v>; -- cgit v1.2.3 From 3c5fe802a7eee3e43e8a8fc771d8a6e85a8016d4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 10 Aug 2026 21:06:04 +0300 Subject: ARM: dts: nxp: imx6qdl-wandboard: Replace clock-frequency in camera sensor node The clock-frequency for camera sensors has been deprecated in favour of the assigned-clocks and assigned-clock-rates properties since 'commit aa1826696a55 ("dt-bindings: media: Deprecate clock-frequency property for camera sensors")' in v6.18. The Linux kernel ov5645 driver has been handling the deprecated property as optional since the same kernel version. Replace the property in the device tree. There are no known users of the property outside of the Linux kernel. In particular, U-Boot doesn't operate the camera. Switching to the new bindings will therefore not introduce any breakage. Signed-off-by: Laurent Pinchart Reviewed-by: Mehdi Djait Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi index 26489eccd5fb..f3aaca039953 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi @@ -137,7 +137,9 @@ pinctrl-0 = <&pinctrl_ov5645>; reg = <0x3c>; clocks = <&clks IMX6QDL_CLK_CKO2>; - clock-frequency = <24000000>; + assigned-clocks = <&clks IMX6QDL_CLK_CKO2>; + assigned-clock-rates = <24000000>; + vdddo-supply = <®_1p8v>; vdda-supply = <®_2p8v>; vddd-supply = <®_1p5v>; -- cgit v1.2.3 From ef92c79a1e4a3e272407d9ceb01327c0b0e32c76 Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Sun, 6 Sep 2026 15:58:21 +0200 Subject: arm64: dts: imx93-11x11-frdm-common: fix the rtc aliases pcf2131 has been assigned the rtc0 alias, but if the bbnsm_rtc gets probed first it will take this name. Properly assign bbnsm_rtc to rtc1 so that this doesn't happen Signed-off-by: Maud Spierings Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi index 5c8fdd77ec15..97d89288db3c 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi @@ -13,6 +13,7 @@ mmc0 = &usdhc1; /* EMMC */ mmc1 = &usdhc2; /* uSD */ rtc0 = &pcf2131; + rtc1 = &bbnsm_rtc; serial0 = &lpuart1; serial4 = &lpuart5; }; -- cgit v1.2.3 From 711ccefdf461c2d448e009116e1ac51f7ef2c10b Mon Sep 17 00:00:00 2001 From: Maud Spierings Date: Sun, 6 Sep 2026 15:58:22 +0200 Subject: arm64: dts: imx93-11x11-frdm: add missing vcc-supply Add the power supply to the pcal6408 gpio expander, it doesn't have the dependency loop like the pcal6524. Signed-off-by: Maud Spierings Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts index 61be6b1c169a..6e8351d12016 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts @@ -45,6 +45,7 @@ #gpio-cells = <2>; gpio-controller; reset-gpios = <&pcal6524 20 GPIO_ACTIVE_LOW>; + vcc-supply = <&buck5>; }; }; -- cgit v1.2.3 From 7ba5290db6bf365e46fb70bf13dc2a47048165ea Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Wed, 2 Sep 2026 18:43:17 +0200 Subject: arm64: dts: imx8mp-var-dart-sonata: Fix Sonata SD I/O supply LDO5 powers the USDHC2 I/O rail on DART-MX8M-PLUS. Without a regulator consumer, the kernel disables LDO5 during late init, which removes the SD card and causes filesystem I/O errors. Reference LDO5 as the Sonata USDHC2 VQMMC supply, so the regulator remains enabled while the SD interface is active. Fixes: 41cd3d91ca859 ("arm64: dts: imx8mp-var-dart: Add support for Variscite Sonata board") Co-developed-by: Luan Rafael Carneiro Signed-off-by: Luan Rafael Carneiro Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp-var-dart-sonata.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-var-dart-sonata.dts b/arch/arm64/boot/dts/freescale/imx8mp-var-dart-sonata.dts index 983d67a0c1de..7f78026e70ff 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-var-dart-sonata.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-var-dart-sonata.dts @@ -511,6 +511,7 @@ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; vmmc-supply = <®_usdhc2_vmmc>; + vqmmc-supply = <&ldo5>; bus-width = <4>; status = "okay"; }; -- cgit v1.2.3 From f322f8f68c2c3291633ead663effa3b25c18f7b1 Mon Sep 17 00:00:00 2001 From: Nora Schiffer Date: Wed, 2 Sep 2026 10:05:37 +0200 Subject: ARM: dts: imx7-tqma7: correctly specify PMIC voltage constraints regulator-(min|max)-microvolt refer to the supported voltages according to board design, not the possible range of the regulators themselves. Update the configuration for the TQMa7x's PMIC and also add a comment regarding the PMIC's VCC_SD switching feature. Fixes: a80a1af6ec8a ("ARM: dts: tq imx7 common board support") Signed-off-by: Nora Schiffer Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi | 40 ++++++++++++++++++------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi index e1f740edfb76..7f49c80fef4c 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi @@ -46,8 +46,8 @@ regulators { sw1a_reg: sw1a { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1225000>; regulator-boot-on; regulator-always-on; regulator-ramp-delay = <6250>; @@ -55,34 +55,33 @@ /* use sw1c_reg to align with pfuze100/pfuze200 */ sw1c_reg: sw1b { - regulator-min-microvolt = <700000>; - regulator-max-microvolt = <1475000>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; regulator-boot-on; regulator-always-on; regulator-ramp-delay = <6250>; }; sw2_reg: sw2 { - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1850000>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; regulator-boot-on; regulator-always-on; }; sw3a_reg: sw3 { - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <1650000>; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; regulator-boot-on; regulator-always-on; }; swbst_reg: swbst { - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5150000>; + /* Not connected and left unconfigured */ }; snvs_reg: vsnvs { - regulator-min-microvolt = <1000000>; + regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; regulator-boot-on; regulator-always-on; @@ -95,18 +94,25 @@ vgen1_reg: vldo1 { regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; + regulator-max-microvolt = <1800000>; regulator-always-on; }; vgen2_reg: vldo2 { - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1550000>; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; regulator-always-on; }; vgen3_reg: vccsd { - regulator-min-microvolt = <2850000>; + /* + * Specified values refer to 3.3V operation; voltage for 1.8V + * operation is derived from this. + * + * The base board should usually mux GPIO1_IO08 to SD1_VSELECT for + * automatic switching of SD card IO voltage. + */ + regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; @@ -118,13 +124,13 @@ }; vgen5_reg: vldo3 { - regulator-min-microvolt = <1800000>; + regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; vgen6_reg: vldo4 { - regulator-min-microvolt = <1800000>; + regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; -- cgit v1.2.3 From cd329bd34c81320c0f9dc8c4149a7d3ef111a651 Mon Sep 17 00:00:00 2001 From: Nora Schiffer Date: Wed, 2 Sep 2026 10:05:38 +0200 Subject: ARM: dts: imx7-tqma7: sort I2C device nodes by address Fix order of the nodes to follow convention. Signed-off-by: Nora Schiffer Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi index 7f49c80fef4c..353af6b320cb 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-tqma7.dtsi @@ -137,6 +137,12 @@ }; }; + /* NXP SE97BTP with temperature sensor + eeprom, TQMa7x 02xx */ + se97b: temperature-sensor@1e { + compatible = "nxp,se97b", "jedec,jc-42.4-temp"; + reg = <0x1e>; + }; + /* LM75A temperature sensor, TQMa7x 01xx */ lm75a: temperature-sensor@48 { compatible = "national,lm75a"; @@ -144,12 +150,6 @@ vs-supply = <&vgen4_reg>; }; - /* NXP SE97BTP with temperature sensor + eeprom, TQMa7x 02xx */ - se97b: temperature-sensor@1e { - compatible = "nxp,se97b", "jedec,jc-42.4-temp"; - reg = <0x1e>; - }; - /* ST M24C64 */ m24c64: eeprom@50 { compatible = "atmel,24c64"; -- cgit v1.2.3 From cc6c96f0bdd7212cb5055c9a38792e35562f2648 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Tue, 1 Sep 2026 14:49:20 +0200 Subject: ARM: dts: imx7d-colibri-emmc: Add VGA overlay Add a device tree overlay for the VGA output on the Colibri iMX7 parallel RGB LCD interface. The VGA output is driven through a non-programmable video DAC without VESA DDC I2C signals to a DVI connector. The overlay is also combined with the Aster, Evaluation Board v3, Iris and Iris v2 carrier board device trees to provide ready-to-use DTBs. Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/Makefile | 21 ++++++++ .../boot/dts/nxp/imx/imx7d-colibri-emmc-vga.dtso | 59 ++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-vga.dtso diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile index e9f95c3b8353..d1272104ef27 100644 --- a/arch/arm/boot/dts/nxp/imx/Makefile +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -436,18 +436,39 @@ imx7d-colibri-emmc-eval-v3-panel-res-touch-7inch-parallel-dtbs := \ imx7d-colibri-emmc-eval-v3.dtb \ imx7d-colibri-emmc-panel-res-touch-7inch-parallel.dtbo +imx7d-colibri-emmc-aster-vga-dtbs := \ + imx7d-colibri-emmc-aster.dtb \ + imx7d-colibri-emmc-vga.dtbo + +imx7d-colibri-emmc-eval-v3-vga-dtbs := \ + imx7d-colibri-emmc-eval-v3.dtb \ + imx7d-colibri-emmc-vga.dtbo + +imx7d-colibri-emmc-iris-vga-dtbs := \ + imx7d-colibri-emmc-iris.dtb \ + imx7d-colibri-emmc-vga.dtbo + +imx7d-colibri-emmc-iris-v2-vga-dtbs := \ + imx7d-colibri-emmc-iris-v2.dtb \ + imx7d-colibri-emmc-vga.dtbo + dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-cl-som-imx7.dtb \ imx7d-colibri-aster.dtb \ imx7d-colibri-emmc-aster.dtb \ imx7d-colibri-emmc-aster-panel-cap-touch-7inch-parallel.dtb \ + imx7d-colibri-emmc-aster-vga.dtb \ imx7d-colibri-emmc-iris.dtb \ + imx7d-colibri-emmc-iris-vga.dtb \ imx7d-colibri-emmc-iris-v2.dtb \ imx7d-colibri-emmc-iris-v2-panel-cap-touch-7inch-parallel.dtb \ + imx7d-colibri-emmc-iris-v2-vga.dtb \ imx7d-colibri-emmc-eval-v3.dtb \ imx7d-colibri-emmc-eval-v3-panel-cap-touch-7inch-parallel-touch-adapter.dtb \ imx7d-colibri-emmc-eval-v3-panel-res-touch-7inch-parallel.dtb \ + imx7d-colibri-emmc-eval-v3-vga.dtb \ imx7d-colibri-emmc-panel-cap-touch-7inch-parallel.dtbo \ + imx7d-colibri-emmc-vga.dtbo \ imx7d-colibri-eval-v3.dtb \ imx7d-colibri-iris.dtb \ imx7d-colibri-iris-v2.dtb \ diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-vga.dtso b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-vga.dtso new file mode 100644 index 000000000000..cda214c13876 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-colibri-emmc-vga.dtso @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * VGA output connected to the Colibri parallel RGB LCD interface through a + * non-programmable video DAC with a DVI connector. + * + * The VGA output is available on multiple carrier boards (including Iris, + * Eval, Aster) without VESA DDC I2C signals. + */ + +/dts-v1/; +/plugin/; + +&{/} { + vga-encoder { + compatible = "dumb-vga-dac"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vga_enc_in: endpoint { + remote-endpoint = <&lcdif_out>; + }; + }; + + port@1 { + reg = <1>; + + vga_enc_out: endpoint { + remote-endpoint = <&dvi_connector_in>; + }; + }; + }; + }; + + dvi-connector { + compatible = "dvi-connector"; + analog; + + port { + dvi_connector_in: endpoint { + remote-endpoint = <&vga_enc_out>; + }; + }; + }; +}; + +&lcdif { + status = "okay"; +}; + +&lcdif_out { + remote-endpoint = <&vga_enc_in>; +}; -- cgit v1.2.3 From 9b58e80264d87f8e0faa80029248b48290bd74a3 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Tue, 1 Sep 2026 00:55:18 +0200 Subject: dt-bindings: arm: fsl: add Variscite VAR-SOM-MX7 boards Add DT compatible strings for the Variscite VAR-SOM-MX7 SoM variants used with the MX7CustomBoard carrier board. Both the first and second hardware revisions are supported, including eMMC and NAND configurations, with WM8731 variants available for the first hardware revision. Acked-by: Conor Dooley Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 46d22d45d2e6..c4c83321c7c3 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -950,6 +950,23 @@ properties: - const: toradex,colibri-imx7d-emmc - const: fsl,imx7d + - description: i.MX7D Variscite Boards based on VAR-SOM-MX7 Module + oneOf: + - items: + - enum: + - variscite,var-som-imx7d-emmc-mx7customboard + - variscite,var-som-imx7d-emmc-wm8731-mx7customboard + - variscite,var-som-imx7d-nand-mx7customboard + - variscite,var-som-imx7d-nand-wm8731-mx7customboard + - const: variscite,var-som-imx7d + - const: fsl,imx7d + - items: + - enum: + - variscite,var-som-imx7d-v2-emmc-mx7customboard + - variscite,var-som-imx7d-v2-nand-mx7customboard + - const: variscite,var-som-imx7d-v2 + - const: fsl,imx7d + - description: i.MX7ULP based Boards items: - enum: -- cgit v1.2.3 From df2c7ea04c8ac239daff1c5c78cbcdca550f8e62 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Tue, 1 Sep 2026 00:55:19 +0200 Subject: ARM: dts: imx7d: add Variscite VAR-SOM-MX7 support Add device tree support for the Variscite VAR-SOM-MX7 system on module. The module is based on the NXP i.MX7Dual SoC and is available in multiple configurations and hardware revisions. Add the common SoM description together with support for: - eMMC storage - NAND storage - WM8731 audio codec - WM8904 audio codec - VAR-SOM-MX7 V2 hardware revision Only SoM-specific peripherals are described here. Carrier board specific interfaces are provided by the respective carrier board device trees. Link: https://variscite.com/system-on-module-som/i-mx-7/var-som-mx7/ Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc.dtsi | 56 +++ .../dts/nxp/imx/imx7d-var-som-mx7customboard.dtsi | 358 ++++++++++++++ arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand.dtsi | 73 +++ arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2.dtsi | 66 +++ .../arm/boot/dts/nxp/imx/imx7d-var-som-wm8731.dtsi | 102 ++++ .../arm/boot/dts/nxp/imx/imx7d-var-som-wm8904.dtsi | 118 +++++ arch/arm/boot/dts/nxp/imx/imx7d-var-som.dtsi | 533 +++++++++++++++++++++ 7 files changed, 1306 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc.dtsi create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-mx7customboard.dtsi create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand.dtsi create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2.dtsi create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8731.dtsi create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8904.dtsi create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som.dtsi diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc.dtsi new file mode 100644 index 000000000000..62f60ec39992 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc.dtsi @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Common dtsi for eMMC support on Variscite VAR-SOM-MX7 + * + * Link: https://variscite.com/system-on-module-som/i-mx-7/var-som-mx7/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +&usdhc3 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_sleep>; + vmmc-supply = <&vgen3_reg>; + assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>; + assigned-clock-rates = <400000000>; + no-1-8-v; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&iomuxc { + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x59 + MX7D_PAD_SD3_CMD__SD3_CMD 0x59 + MX7D_PAD_SD3_CLK__SD3_CLK 0x19 + MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59 + MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59 + MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59 + MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59 + MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59 + MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59 + MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59 + MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59 + >; + }; + + pinctrl_usdhc3_sleep: usdhc3-sleepgrp { + fsl,pins = < + MX7D_PAD_SD3_RESET_B__GPIO6_IO11 0x10 + MX7D_PAD_SD3_CMD__GPIO6_IO1 0x10 + MX7D_PAD_SD3_CLK__GPIO6_IO0 0x10 + MX7D_PAD_SD3_DATA0__GPIO6_IO2 0x10 + MX7D_PAD_SD3_DATA1__GPIO6_IO3 0x10 + MX7D_PAD_SD3_DATA2__GPIO6_IO4 0x10 + MX7D_PAD_SD3_DATA3__GPIO6_IO5 0x10 + MX7D_PAD_SD3_DATA4__GPIO6_IO6 0x10 + MX7D_PAD_SD3_DATA5__GPIO6_IO7 0x10 + MX7D_PAD_SD3_DATA6__GPIO6_IO8 0x10 + MX7D_PAD_SD3_DATA7__GPIO6_IO9 0x10 + >; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-mx7customboard.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-mx7customboard.dtsi new file mode 100644 index 000000000000..d798b021f8e0 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-mx7customboard.dtsi @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Variscite VAR-MX7CustomBoard carrier board for VAR-SOM-MX7 + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/ { + chosen { + stdout-path = &uart1; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_keys>; + + key-back { + label = "Back"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + key-menu { + label = "Menu"; + gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + key-home { + label = "Home"; + gpios = <&gpio2 29 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + led-d10 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_hsic_hub_connect: regulator-hsic-hub-connect { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hsic_hub_connect>; + regulator-name = "reg_hsic_hub_connect"; + gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + reg_hsic_hub_pwr_on: regulator-hsic-hub-pwr-on { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hsic_hub_pwr>; + regulator-name = "hsic_hub_pwr_on"; + gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usb_otg1_vbus: regulator-otg1-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg1_pwr>; + regulator-name = "usb_otg1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usb_otg2_vbus: regulator-otg2-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg2_pwr>; + regulator-name = "usb_otg2_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&clks { + assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>; + assigned-clock-rates = <884736000>; +}; + +&ecspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi2>; + cs-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + status = "okay"; +}; + +&i2c2 { + /* DS1337 RTC module */ + rtc@68 { + compatible = "dallas,ds1337"; + reg = <0x68>; + }; +}; + +&i2c4 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c4>; + pinctrl-1 = <&pinctrl_i2c4_gpio>; + scl-gpios = <&gpio4 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + ft5x06_ts: touchscreen@38 { + compatible = "edt,edt-ft5206"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_touch>; + interrupt-parent = <&gpio2>; + interrupts = <30 IRQ_TYPE_EDGE_FALLING>; + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; + touchscreen-inverted-x; + touchscreen-inverted-y; + }; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpios = <&gpio2 31 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&pwm2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; + status = "okay"; +}; + +&snvs_poweroff { + status = "okay"; +}; + +&snvs_pwrkey { + status = "okay"; +}; + +&snvs_rtc { + status = "disabled"; +}; + +/* DEBUG */ +&uart1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_uart1>; + pinctrl-1 = <&pinctrl_uart1_sleep>; + assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; + uart-has-rtscts; + status = "okay"; +}; + +&usbh { + disable-over-current; + vbus-supply = <®_hsic_hub_pwr_on>; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "host"; + disable-over-current; + vbus-supply = <®_usb_otg1_vbus>; + status = "okay"; +}; + +&usbotg2 { + dr_mode = "host"; + disable-over-current; + vbus-supply = <®_usb_otg2_vbus>; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_usdhc1_gpio>; + cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; + no-1-8-v; + keep-power-in-suspend; + status = "okay"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; +}; + +&iomuxc { + pinctrl_gpio_keys: gpio-keysgrp { + fsl,pins = < + MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x32 + MX7D_PAD_EPDC_BDR1__GPIO2_IO29 0x32 + MX7D_PAD_GPIO1_IO11__GPIO1_IO11 0x32 + >; + }; + + pinctrl_gpio_leds: gpio-ledsgrp { + fsl,pins = < + MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x59 + >; + }; + + pinctrl_ecspi2: ecspi2grp { + fsl,pins = < + MX7D_PAD_ECSPI2_MISO__ECSPI2_MISO 0x2 + MX7D_PAD_ECSPI2_MOSI__ECSPI2_MOSI 0x2 + MX7D_PAD_ECSPI2_SCLK__ECSPI2_SCLK 0x2 + MX7D_PAD_ECSPI2_SS0__GPIO4_IO23 0x2 + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX7D_PAD_I2C3_SCL__FLEXCAN2_RX 0x59 + MX7D_PAD_I2C3_SDA__FLEXCAN2_TX 0x59 + >; + }; + + pinctrl_hsic_hub_connect: hsichubconnectgrp { + fsl,pins = < + MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x59 + >; + }; + + pinctrl_hsic_hub_pwr: hsichubpwrgrp { + fsl,pins = < + MX7D_PAD_GPIO1_IO10__GPIO1_IO10 0x59 + >; + }; + + pinctrl_i2c4: i2c4grp { + fsl,pins = < + MX7D_PAD_I2C4_SDA__I2C4_SDA 0x4000007f + MX7D_PAD_I2C4_SCL__I2C4_SCL 0x4000007f + >; + }; + + pinctrl_i2c4_gpio: i2c4gpiogrp { + fsl,pins = < + MX7D_PAD_I2C4_SDA__GPIO4_IO15 0x4000007f + MX7D_PAD_I2C4_SCL__GPIO4_IO14 0x4000007f + >; + }; + + pinctrl_pcie: pciegrp { + fsl,pins = < + MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31 0x79 + >; + }; + + pinctrl_touch: touchgrp { + fsl,pins = < + MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30 0x80000000 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79 + MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX 0x79 + >; + }; + + pinctrl_uart1_sleep: uart1sleep-grp { + fsl,pins = < + MX7D_PAD_UART1_TX_DATA__GPIO4_IO1 0x10 + MX7D_PAD_UART1_RX_DATA__GPIO4_IO0 0x10 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX7D_PAD_LCD_ENABLE__UART2_DCE_TX 0x79 + MX7D_PAD_LCD_CLK__UART2_DCE_RX 0x79 + MX7D_PAD_LCD_VSYNC__UART2_DCE_CTS 0x79 + MX7D_PAD_LCD_HSYNC__UART2_DCE_RTS 0x79 + >; + }; + + pinctrl_usdhc1_gpio: usdhc1-gpiogrp { + fsl,pins = < + MX7D_PAD_SD1_CD_B__GPIO5_IO0 0x59 + MX7D_PAD_GPIO1_IO08__SD1_VSELECT 0x59 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX7D_PAD_SD1_CMD__SD1_CMD 0x59 + MX7D_PAD_SD1_CLK__SD1_CLK 0x19 + MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59 + MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59 + MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59 + MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59 + >; + }; +}; + +&iomuxc_lpsr { + pinctrl_pwm2: pwm2grp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO02__PWM2_OUT 0x110b0 + >; + }; + + pinctrl_usbotg1_pwr: usbotg1pwrgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5 0x14 + >; + }; + + pinctrl_usbotg2_pwr: usbotg2pwrgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO07__GPIO1_IO7 0x14 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO00__WDOG1_WDOG_B 0x74 + >; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand.dtsi new file mode 100644 index 000000000000..d2c3b9e6007e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand.dtsi @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Common dtsi for NAND support on Variscite VAR-SOM-MX7 + * + * Link: https://variscite.com/system-on-module-som/i-mx-7/var-som-mx7/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +&gpmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpmi_nand>; + status = "okay"; + + nand@0 { + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "spl"; + reg = <0x00000000 0x00200000>; + }; + + partition@200000 { + label = "u-boot"; + reg = <0x00200000 0x00200000>; + }; + + partition@400000 { + label = "u-boot_env"; + reg = <0x00400000 0x00200000>; + }; + + partition@600000 { + label = "kernel"; + reg = <0x00600000 0x00c00000>; + }; + + partition@1200000 { + label = "rootfs"; + reg = <0x01200000 0x3ee00000>; + }; + }; + }; +}; + +&iomuxc { + pinctrl_gpmi_nand: gpminandgrp { + fsl,pins = < + MX7D_PAD_SD3_CLK__NAND_CLE 0x71 + MX7D_PAD_SD3_CMD__NAND_ALE 0x71 + MX7D_PAD_SAI1_MCLK__NAND_WP_B 0x71 + MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B 0x71 + MX7D_PAD_SAI1_RX_DATA__NAND_CE1_B 0x71 + MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74 + MX7D_PAD_SD3_STROBE__NAND_RE_B 0x71 + MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71 + MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71 + MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71 + MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71 + MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71 + MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71 + MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71 + MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71 + MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71 + >; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2.dtsi new file mode 100644 index 000000000000..8aa9d0950a97 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2.dtsi @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * dtsi for Variscite VAR-SOM-MX7 V2 + * + * Changelog link: https://dev.variscite.com/var-som-mx7/changelog/#var-som-mx7_v2-v20 + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/ { + model = "Variscite i.MX7 Dual VAR-SOM-MX7 V2"; + compatible = "variscite,var-som-imx7d-v2", "fsl,imx7d"; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + post-power-on-delay-ms = <100>; + power-off-delay-us = <10000>; + reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; + }; +}; + +&fec1 { + /* + * The required RGMII TX and RX 2ns delays are implemented directly + * in hardware via passive delay elements on the SOM PCB. + * No delay configuration is needed in software via PHY driver. + */ + phy-mode = "rgmii"; +}; + +&fec2 { + /* + * The required RGMII TX and RX 2ns delays are implemented directly + * in hardware via passive delay elements on the SOM PCB. + * No delay configuration is needed in software via PHY driver. + */ + phy-mode = "rgmii"; +}; + +&pinctrl_wlan { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x09 + >; +}; + +&pinctrl_wlan_sleep { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x10 + >; +}; + +/* BT */ +&uart3 { + bluetooth_iw61x: bluetooth { + compatible = "nxp,88w8987-bt"; + }; +}; + +/* WiFi */ +&usdhc2 { + /delete-property/ #address-cells; + /delete-property/ #size-cells; + mmc-pwrseq = <&wifi_pwrseq>; + /delete-node/ wifi@1; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8731.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8731.dtsi new file mode 100644 index 000000000000..ab05de43cc53 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8731.dtsi @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Common dtsi for WM8731 support on Variscite VAR-SOM-MX7 + * + * Link: https://variscite.com/system-on-module-som/i-mx-7/var-som-mx7/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/ { + codec_wm8731: sound { + compatible = "simple-audio-card"; + simple-audio-card,bitclock-master = <&sound_master>; + simple-audio-card,format = "i2s"; + simple-audio-card,frame-master = <&sound_master>; + simple-audio-card,name = "wm8731audio"; + simple-audio-card,routing = + "Headphone Jack", "RHPOUT", + "Headphone Jack", "LHPOUT", + "LLINEIN", "Line Jack", + "RLINEIN", "Line Jack", + "MICIN", "Mic Bias", + "Mic Bias", "Mic Jack"; + simple-audio-card,widgets = + "Headphone", "Headphone Jack", + "Line", "Line Jack", + "Microphone", "Mic Jack"; + + sound_master: simple-audio-card,cpu { + sound-dai = <&sai1>; + }; + + simple-audio-card,codec { + sound-dai = <&wm8731>; + system-clock-frequency = <12288000>; + }; + }; +}; + +&i2c2 { + wm8731: audio-codec@1a { + compatible = "wlf,wm8731"; + reg = <0x1a>; + #sound-dai-cells = <0>; + AVDD-supply = <&vgen6_reg>; + DBVDD-supply = <&vgen6_reg>; + DCVDD-supply = <&vgen6_reg>; + HPVDD-supply = <&vgen6_reg>; + clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>; + clock-names = "mclk"; + assigned-clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_SRC>, + <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>; + assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>; + assigned-clock-rates = <0>, <12288000>; + }; +}; + +&sai1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_sai1>, <&pinctrl_sai1_mclk>; + pinctrl-1 = <&pinctrl_sai1_sleep>, <&pinctrl_sai1_mclk_sleep>; + assigned-clocks = <&clks IMX7D_SAI1_ROOT_SRC>, + <&clks IMX7D_SAI1_ROOT_CLK>; + assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>; + assigned-clock-rates = <0>, <36864000>; + status = "okay"; +}; + +&iomuxc { + pinctrl_sai1: sai1grp { + fsl,pins = < + MX7D_PAD_ENET1_RX_CLK__SAI1_TX_BCLK 0x1f + MX7D_PAD_ENET1_CRS__SAI1_TX_SYNC 0x1f + MX7D_PAD_ENET1_COL__SAI1_TX_DATA0 0x30 + MX7D_PAD_ENET1_TX_CLK__SAI1_RX_DATA0 0x1f + >; + }; + + pinctrl_sai1_sleep: sai1-sleepgrp { + fsl,pins = < + MX7D_PAD_ENET1_RX_CLK__GPIO7_IO13 0x10 + MX7D_PAD_ENET1_CRS__GPIO7_IO14 0x10 + MX7D_PAD_ENET1_COL__GPIO7_IO15 0x10 + MX7D_PAD_ENET1_TX_CLK__GPIO7_IO12 0x10 + >; + }; +}; + +&iomuxc_lpsr { + pinctrl_sai1_mclk: sai1-mclkgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO01__SAI1_MCLK 0x1f + >; + }; + + pinctrl_sai1_mclk_sleep: sai1-mclksleepgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO01__GPIO1_IO1 0x10 + >; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8904.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8904.dtsi new file mode 100644 index 000000000000..b56f3680edcf --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-wm8904.dtsi @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Common dtsi for WM8904 support on Variscite VAR-SOM-MX7 + * + * Link: https://variscite.com/system-on-module-som/i-mx-7/var-som-mx7/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/ { + codec_wm8904: sound { + compatible = "simple-audio-card"; + simple-audio-card,bitclock-master = <&dailink_master>; + simple-audio-card,format = "i2s"; + simple-audio-card,frame-master = <&dailink_master>; + simple-audio-card,name = "wm8904-audio"; + simple-audio-card,routing = + "Headphone Jack", "HPOUTL", + "Headphone Jack", "HPOUTR", + "IN2L", "Line In Jack", + "IN2R", "Line In Jack", + "IN1L", "Microphone Jack", + "IN1R", "Microphone Jack", + "Microphone Jack", "MICBIAS"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Line", "Line In Jack"; + simple-audio-card,mclk-fs = <256>; + + dailink_master: simple-audio-card,codec { + sound-dai = <&wm8904>; + }; + + simple-audio-card,cpu { + sound-dai = <&sai1>; + }; + }; +}; + +&i2c2 { + wm8904: audio-codec@1a { + compatible = "wlf,wm8904"; + reg = <0x1a>; + #sound-dai-cells = <0>; + clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>; + clock-names = "mclk"; + AVDD-supply = <&vgen6_reg>; + CPVDD-supply = <&vgen6_reg>; + DCVDD-supply = <&vgen6_reg>; + DBVDD-supply = <&vgen6_reg>; + MICVDD-supply = <&vgen6_reg>; + wlf,drc-cfg-names = "default", "peaklimiter", "tradition", + "soft", "music"; + /* + * Config registers per name, respectively: + * KNEE_IP = 0, KNEE_OP = 0, HI_COMP = 1, LO_COMP = 1 + * KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1 + * KNEE_IP = -42, KNEE_OP = -3, HI_COMP = 0, LO_COMP = 1 + * KNEE_IP = -45, KNEE_OP = -9, HI_COMP = 1/8, LO_COMP = 1 + * KNEE_IP = -30, KNEE_OP = -10.5, HI_COMP = 1/4, LO_COMP = 1 + */ + wlf,drc-cfg-regs = /bits/ 16 <0x01af 0x3248 0x0000 0x0000>, + /bits/ 16 <0x04af 0x324b 0x0010 0x0408>, + /bits/ 16 <0x04af 0x324b 0x0028 0x0704>, + /bits/ 16 <0x04af 0x324b 0x0018 0x078c>, + /bits/ 16 <0x04af 0x324b 0x0010 0x050e>; + /* GPIO1 = DMIC_CLK, don't touch others */ + wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>; + }; +}; + +&sai1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_sai1>, <&pinctrl_sai1_mclk>; + pinctrl-1 = <&pinctrl_sai1_sleep>, <&pinctrl_sai1_mclk_sleep>; + assigned-clocks = <&clks IMX7D_SAI1_ROOT_SRC>, + <&clks IMX7D_SAI1_ROOT_CLK>; + assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>; + assigned-clock-rates = <0>, <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + +&iomuxc { + pinctrl_sai1: sai1grp { + fsl,pins = < + MX7D_PAD_ENET1_RX_CLK__SAI1_TX_BCLK 0x1f + MX7D_PAD_ENET1_CRS__SAI1_TX_SYNC 0x1f + MX7D_PAD_ENET1_COL__SAI1_TX_DATA0 0x30 + MX7D_PAD_ENET1_TX_CLK__SAI1_RX_DATA0 0x1f + >; + }; + + pinctrl_sai1_sleep: sai1-sleepgrp { + fsl,pins = < + MX7D_PAD_ENET1_RX_CLK__GPIO7_IO13 0x10 + MX7D_PAD_ENET1_CRS__GPIO7_IO14 0x10 + MX7D_PAD_ENET1_COL__GPIO7_IO15 0x10 + MX7D_PAD_ENET1_TX_CLK__GPIO7_IO12 0x10 + >; + }; +}; + +&iomuxc_lpsr { + pinctrl_sai1_mclk: sai1-mclkgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO01__SAI1_MCLK 0x1f + >; + }; + + pinctrl_sai1_mclk_sleep: sai1-mclksleepgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO01__GPIO1_IO1 0x10 + >; + }; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som.dtsi b/arch/arm/boot/dts/nxp/imx/imx7d-var-som.dtsi new file mode 100644 index 000000000000..255cf4490077 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som.dtsi @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Common dtsi for Variscite VAR-SOM-MX7 + * + * Link: https://variscite.com/system-on-module-som/i-mx-7/var-som-mx7/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +#include +#include "imx7d.dtsi" + +/ { + model = "Variscite i.MX7 Dual VAR-SOM-MX7"; + compatible = "variscite,var-som-imx7d", "fsl,imx7d"; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x80000000>; + }; + + reg_phy_vddio: regulator-phy-vddio { + compatible = "regulator-fixed"; + regulator-name = "vddio-1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + reg_vmmc_wl: regulator-vmmc-wl { + compatible = "regulator-fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "wlreg_on"; + }; + + reg_vref_1v8: regulator-vref-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vref-1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + +}; + +&adc1 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&adc2 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&sw1a_reg>; +}; + +&cpu1 { + cpu-supply = <&sw1a_reg>; +}; + +&ecspi1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_ecspi1>; + pinctrl-1 = <&pinctrl_ecspi1_sleep>; + cs-gpios = <&gpio4 19 GPIO_ACTIVE_LOW>; + status = "okay"; + + /* Resistive touch controller */ + ads7846_ts: touchscreen@0 { + reg = <0>; + compatible = "ti,ads7846"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_restouch>; + interrupt-parent = <&gpio1>; + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + spi-max-frequency = <1500000>; + pendown-gpio = <&gpio1 9 GPIO_ACTIVE_LOW>; + ti,x-min = /bits/ 16 <125>; + ti,x-max = /bits/ 16 <4008>; + ti,y-min = /bits/ 16 <282>; + ti,y-max = /bits/ 16 <3864>; + ti,x-plate-ohms = /bits/ 16 <180>; + ti,pressure-max = /bits/ 16 <255>; + ti,debounce-max = /bits/ 16 <10>; + ti,debounce-tol = /bits/ 16 <3>; + ti,debounce-rep = /bits/ 16 <1>; + ti,settle-delay-usec = /bits/ 16 <150>; + ti,keep-vref-on; + }; +}; + +&fec1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_enet1>, + <&pinctrl_enet1_rst>, + <&pinctrl_enet2_rst>; + pinctrl-1 = <&pinctrl_enet1_sleep>, + <&pinctrl_enet1_rst_sleep>, + <&pinctrl_enet2_rst_sleep>; + phy-supply = <&vgen3_reg>; + assigned-clocks = <&clks IMX7D_ENET_PHY_REF_ROOT_SRC>, + <&clks IMX7D_ENET_AXI_ROOT_SRC>, + <&clks IMX7D_ENET1_TIME_ROOT_SRC>, + <&clks IMX7D_ENET1_TIME_ROOT_CLK>, + <&clks IMX7D_ENET_AXI_ROOT_CLK>; + assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_25M_CLK>, + <&clks IMX7D_PLL_ENET_MAIN_250M_CLK>, + <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>; + assigned-clock-rates = <0>, <0>, <0>, <100000000>, <250000000>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>; + reset-assert-us = <20000>; + reset-deassert-us = <80000>; + vddio-supply = <®_phy_vddio>; + }; + + ethphy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + reset-gpios = <&gpio4 3 GPIO_ACTIVE_LOW>; + reset-assert-us = <20000>; + reset-deassert-us = <80000>; + vddio-supply = <®_phy_vddio>; + }; + }; +}; + +&fec2 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_enet2>; + pinctrl-1 = <&pinctrl_enet2_sleep>; + phy-supply = <&vgen3_reg>; + assigned-clocks = <&clks IMX7D_ENET_PHY_REF_ROOT_SRC>, + <&clks IMX7D_ENET_AXI_ROOT_SRC>, + <&clks IMX7D_ENET2_TIME_ROOT_SRC>, + <&clks IMX7D_ENET2_TIME_ROOT_CLK>, + <&clks IMX7D_ENET_AXI_ROOT_CLK>; + assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_25M_CLK>, + <&clks IMX7D_PLL_ENET_MAIN_250M_CLK>, + <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>; + assigned-clock-rates = <0>, <0>, <0>, <100000000>, <250000000>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy1>; + status = "okay"; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio4 8 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 9 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + pfuze300: pmic@8 { + compatible = "fsl,pfuze3000"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1a { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + /* use sw1c_reg to align with pfuze100/pfuze200 */ + sw1c_reg: sw1b { + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1475000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3a_reg: sw3 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1650000>; + regulator-boot-on; + regulator-always-on; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-boot-on; + regulator-always-on; + }; + + vgen1_reg: vldo1 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen2_reg: vldo2 { + status = "disabled"; + }; + + vgen3_reg: vccsd { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vgen4_reg: v33 { + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + regulator-always-on; + }; + + vgen5_reg: vldo3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vldo4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + scl-gpios = <&gpio4 10 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 11 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + +®_1p0d { + vin-supply = <&sw2_reg>; +}; + +®_1p2 { + vin-supply = <&sw2_reg>; +}; + +/* BT */ +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_bt>; + assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>; + assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>; + uart-has-rtscts; + status = "okay"; +}; + +/* WiFi */ +&usdhc2 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_wlan>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_wlan>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_wlan>; + pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_wlan_sleep>; + keep-power-in-suspend; + non-removable; + vmmc-supply = <®_vmmc_wl>; + status = "okay"; + + brcmf: wifi@1 { + compatible = "brcm,bcm4329-fmac"; + reg = <1>; + }; +}; + +&iomuxc { + /* GPIO Used in User Space init script */ + pinctrl_bt: btgrp { + fsl,pins = < + MX7D_PAD_GPIO1_IO14__GPIO1_IO14 0x80000000 + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX7D_PAD_ECSPI1_MISO__ECSPI1_MISO 0x2 + MX7D_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x2 + MX7D_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x2 + MX7D_PAD_ECSPI1_SS0__GPIO4_IO19 0x2 + >; + }; + + pinctrl_ecspi1_sleep: ecspi1-sleepgrp { + fsl,pins = < + MX7D_PAD_ECSPI1_MISO__GPIO4_IO18 0x10 + MX7D_PAD_ECSPI1_MOSI__GPIO4_IO17 0x10 + MX7D_PAD_ECSPI1_SCLK__GPIO4_IO16 0x10 + >; + }; + + pinctrl_enet1: enet1grp { + fsl,pins = < + MX7D_PAD_SD2_CD_B__ENET1_MDIO 0x3 + MX7D_PAD_SD2_WP__ENET1_MDC 0x3 + MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x1 + MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0 0x1 + MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1 0x1 + MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2 0x1 + MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3 0x1 + MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x1 + MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC 0x1 + MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0 0x1 + MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1 0x1 + MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2 0x1 + MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3 0x1 + MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL 0x1 + >; + }; + + pinctrl_enet1_rst: enet1rstgrp { + fsl,pins = < + MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x59 + >; + }; + + pinctrl_enet1_sleep: enet1-sleepgrp { + fsl,pins = < + MX7D_PAD_SD2_CD_B__GPIO5_IO9 0x10 + MX7D_PAD_SD2_WP__GPIO5_IO10 0x10 + MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11 0x10 + MX7D_PAD_ENET1_RGMII_TD0__GPIO7_IO6 0x10 + MX7D_PAD_ENET1_RGMII_TD1__GPIO7_IO7 0x10 + MX7D_PAD_ENET1_RGMII_TD2__GPIO7_IO8 0x10 + MX7D_PAD_ENET1_RGMII_TD3__GPIO7_IO9 0x10 + MX7D_PAD_ENET1_RGMII_TX_CTL__GPIO7_IO10 0x10 + MX7D_PAD_ENET1_RGMII_RXC__GPIO7_IO5 0x10 + MX7D_PAD_ENET1_RGMII_RD0__GPIO7_IO0 0x10 + MX7D_PAD_ENET1_RGMII_RD1__GPIO7_IO1 0x10 + MX7D_PAD_ENET1_RGMII_RD2__GPIO7_IO2 0x10 + MX7D_PAD_ENET1_RGMII_RD3__GPIO7_IO3 0x10 + MX7D_PAD_ENET1_RGMII_RX_CTL__GPIO7_IO4 0x10 + >; + }; + + pinctrl_enet1_rst_sleep: enet1-rstsleepgrp { + fsl,pins = < + MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x10 + >; + }; + + pinctrl_enet2: enet2grp { + fsl,pins = < + MX7D_PAD_EPDC_GDSP__ENET2_RGMII_TXC 0x1 + MX7D_PAD_EPDC_SDCE2__ENET2_RGMII_TD0 0x1 + MX7D_PAD_EPDC_SDCE3__ENET2_RGMII_TD1 0x1 + MX7D_PAD_EPDC_GDCLK__ENET2_RGMII_TD2 0x1 + MX7D_PAD_EPDC_GDOE__ENET2_RGMII_TD3 0x1 + MX7D_PAD_EPDC_GDRL__ENET2_RGMII_TX_CTL 0x1 + MX7D_PAD_EPDC_SDCE1__ENET2_RGMII_RXC 0x1 + MX7D_PAD_EPDC_SDCLK__ENET2_RGMII_RD0 0x1 + MX7D_PAD_EPDC_SDLE__ENET2_RGMII_RD1 0x1 + MX7D_PAD_EPDC_SDOE__ENET2_RGMII_RD2 0x1 + MX7D_PAD_EPDC_SDSHR__ENET2_RGMII_RD3 0x1 + MX7D_PAD_EPDC_SDCE0__ENET2_RGMII_RX_CTL 0x1 + >; + }; + + pinctrl_enet2_rst: enet2rstgrp { + fsl,pins = < + MX7D_PAD_UART2_TX_DATA__GPIO4_IO3 0x59 + >; + }; + + pinctrl_enet2_sleep: enet2-sleepgrp { + fsl,pins = < + MX7D_PAD_EPDC_GDSP__GPIO2_IO27 0x10 + MX7D_PAD_EPDC_SDCE2__GPIO2_IO22 0x10 + MX7D_PAD_EPDC_SDCE3__GPIO2_IO23 0x10 + MX7D_PAD_EPDC_GDCLK__GPIO2_IO24 0x10 + MX7D_PAD_EPDC_GDOE__GPIO2_IO25 0x10 + MX7D_PAD_EPDC_GDRL__GPIO2_IO26 0x10 + MX7D_PAD_EPDC_SDCE1__GPIO2_IO21 0x10 + MX7D_PAD_EPDC_SDCLK__GPIO2_IO16 0x10 + MX7D_PAD_EPDC_SDLE__GPIO2_IO17 0x10 + MX7D_PAD_EPDC_SDOE__GPIO2_IO18 0x10 + MX7D_PAD_EPDC_SDSHR__GPIO2_IO19 0x10 + MX7D_PAD_EPDC_SDCE0__GPIO2_IO20 0x10 + >; + }; + + pinctrl_enet2_rst_sleep: enet2-rstsleepgrp { + fsl,pins = < + MX7D_PAD_UART2_TX_DATA__GPIO4_IO3 0x10 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f + MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f + >; + }; + + pinctrl_i2c1_gpio: i2c1gpiogrp { + fsl,pins = < + MX7D_PAD_I2C1_SDA__GPIO4_IO9 0x4000007f + MX7D_PAD_I2C1_SCL__GPIO4_IO8 0x4000007f + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX7D_PAD_I2C2_SDA__I2C2_SDA 0x4000007f + MX7D_PAD_I2C2_SCL__I2C2_SCL 0x4000007f + >; + }; + + pinctrl_i2c2_gpio: i2c2gpiogrp { + fsl,pins = < + MX7D_PAD_I2C2_SDA__GPIO4_IO11 0x4000007f + MX7D_PAD_I2C2_SCL__GPIO4_IO10 0x4000007f + >; + }; + + pinctrl_restouch: restouchgrp { + fsl,pins = < + MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x59 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX7D_PAD_UART3_TX_DATA__UART3_DCE_TX 0x79 + MX7D_PAD_UART3_RX_DATA__UART3_DCE_RX 0x79 + MX7D_PAD_UART3_CTS_B__UART3_DCE_CTS 0x79 + MX7D_PAD_UART3_RTS_B__UART3_DCE_RTS 0x79 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x59 + MX7D_PAD_SD2_CLK__SD2_CLK 0x19 + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x59 + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x59 + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x59 + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x59 + >; + }; + + pinctrl_usdhc2_sleep: usdhc2-sleepgrp { + fsl,pins = < + MX7D_PAD_SD2_CMD__GPIO5_IO13 0x10 + MX7D_PAD_SD2_CLK__GPIO5_IO12 0x10 + MX7D_PAD_SD2_DATA0__GPIO5_IO14 0x10 + MX7D_PAD_SD2_DATA1__GPIO5_IO15 0x10 + MX7D_PAD_SD2_DATA2__GPIO5_IO16 0x10 + MX7D_PAD_SD2_DATA3__GPIO5_IO17 0x10 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x5a + MX7D_PAD_SD2_CLK__SD2_CLK 0x1a + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5a + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5a + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5a + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5a + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { + fsl,pins = < + MX7D_PAD_SD2_CMD__SD2_CMD 0x5b + MX7D_PAD_SD2_CLK__SD2_CLK 0x1b + MX7D_PAD_SD2_DATA0__SD2_DATA0 0x5b + MX7D_PAD_SD2_DATA1__SD2_DATA1 0x5b + MX7D_PAD_SD2_DATA2__SD2_DATA2 0x5b + MX7D_PAD_SD2_DATA3__SD2_DATA3 0x5b + >; + }; +}; + +&iomuxc_lpsr { + /* GPIO Used in User Space init script */ + pinctrl_wlan: wlangrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x09 + >; + }; + + pinctrl_wlan_sleep: wlan-sleepgrp { + fsl,pins = < + MX7D_PAD_LPSR_GPIO1_IO04__GPIO1_IO4 0x10 + >; + }; +}; -- cgit v1.2.3 From 40f1b207d21530e10f05b9eaf892b4358a1f1151 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Tue, 1 Sep 2026 00:55:20 +0200 Subject: ARM: dts: imx7d: add Variscite MX7CustomBoard support Add device tree support for the Variscite MX7CustomBoard carrier board with the VAR-SOM-MX7 system on module. This includes supported board configurations for both VAR-SOM-MX7 hardware revisions, with eMMC and NAND variants, and WM8731 variants for the first hardware revision. Link: https://www.variscite.com/carrier-boards/var-mx7customboard/ Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/Makefile | 6 ++++++ .../nxp/imx/imx7d-var-som-emmc-mx7customboard.dts | 23 +++++++++++++++++++++ .../imx7d-var-som-emmc-wm8731-mx7customboard.dts | 23 +++++++++++++++++++++ .../nxp/imx/imx7d-var-som-nand-mx7customboard.dts | 23 +++++++++++++++++++++ .../imx7d-var-som-nand-wm8731-mx7customboard.dts | 23 +++++++++++++++++++++ .../imx/imx7d-var-som-v2-emmc-mx7customboard.dts | 24 ++++++++++++++++++++++ .../imx/imx7d-var-som-v2-nand-mx7customboard.dts | 24 ++++++++++++++++++++++ 7 files changed, 146 insertions(+) create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-mx7customboard.dts create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-wm8731-mx7customboard.dts create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-mx7customboard.dts create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-wm8731-mx7customboard.dts create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-emmc-mx7customboard.dts create mode 100644 arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-nand-mx7customboard.dts diff --git a/arch/arm/boot/dts/nxp/imx/Makefile b/arch/arm/boot/dts/nxp/imx/Makefile index d1272104ef27..c5caca92ea10 100644 --- a/arch/arm/boot/dts/nxp/imx/Makefile +++ b/arch/arm/boot/dts/nxp/imx/Makefile @@ -487,6 +487,12 @@ dtb-$(CONFIG_SOC_IMX7D) += \ imx7d-sdb-reva.dtb \ imx7d-sdb-sht11.dtb \ imx7d-smegw01.dtb \ + imx7d-var-som-emmc-mx7customboard.dtb \ + imx7d-var-som-emmc-wm8731-mx7customboard.dtb \ + imx7d-var-som-nand-mx7customboard.dtb \ + imx7d-var-som-nand-wm8731-mx7customboard.dtb \ + imx7d-var-som-v2-emmc-mx7customboard.dtb \ + imx7d-var-som-v2-nand-mx7customboard.dtb \ imx7d-zii-rmu2.dtb \ imx7d-zii-rpu2.dtb \ imx7s-colibri-aster.dtb \ diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-mx7customboard.dts b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-mx7customboard.dts new file mode 100644 index 000000000000..594ee2d2d23a --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-mx7customboard.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * VAR-MX7CustomBoard for VAR-SOM-MX7 with eMMC + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/dts-v1/; + +#include "imx7d-var-som.dtsi" +#include "imx7d-var-som-emmc.dtsi" +#include "imx7d-var-som-wm8904.dtsi" +#include "imx7d-var-som-mx7customboard.dtsi" + +/ { + model = "Variscite VAR-SOM-MX7 with eMMC & WM8904 on VAR-MX7CustomBoard"; + compatible = "variscite,var-som-imx7d-emmc-mx7customboard", + "variscite,var-som-imx7d", + "fsl,imx7d"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-wm8731-mx7customboard.dts b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-wm8731-mx7customboard.dts new file mode 100644 index 000000000000..94c4b1fa5d6c --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-emmc-wm8731-mx7customboard.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * VAR-MX7CustomBoard for VAR-SOM-MX7 with eMMC and WM8731 + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/dts-v1/; + +#include "imx7d-var-som.dtsi" +#include "imx7d-var-som-emmc.dtsi" +#include "imx7d-var-som-wm8731.dtsi" +#include "imx7d-var-som-mx7customboard.dtsi" + +/ { + model = "Variscite VAR-SOM-MX7 with eMMC & WM8731 on VAR-MX7CustomBoard"; + compatible = "variscite,var-som-imx7d-emmc-wm8731-mx7customboard", + "variscite,var-som-imx7d", + "fsl,imx7d"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-mx7customboard.dts b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-mx7customboard.dts new file mode 100644 index 000000000000..d3fbf3b4b5a3 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-mx7customboard.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * VAR-MX7CustomBoard for VAR-SOM-MX7 with NAND + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/dts-v1/; + +#include "imx7d-var-som.dtsi" +#include "imx7d-var-som-nand.dtsi" +#include "imx7d-var-som-wm8904.dtsi" +#include "imx7d-var-som-mx7customboard.dtsi" + +/ { + model = "Variscite VAR-SOM-MX7 with NAND flash & WM8904 on VAR-MX7CustomBoard"; + compatible = "variscite,var-som-imx7d-nand-mx7customboard", + "variscite,var-som-imx7d", + "fsl,imx7d"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-wm8731-mx7customboard.dts b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-wm8731-mx7customboard.dts new file mode 100644 index 000000000000..603b2dbf4c8e --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-nand-wm8731-mx7customboard.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * VAR-MX7CustomBoard for VAR-SOM-MX7 with NAND and WM8731 + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/dts-v1/; + +#include "imx7d-var-som.dtsi" +#include "imx7d-var-som-nand.dtsi" +#include "imx7d-var-som-wm8731.dtsi" +#include "imx7d-var-som-mx7customboard.dtsi" + +/ { + model = "Variscite VAR-SOM-MX7 with NAND flash & WM8731 on VAR-MX7CustomBoard"; + compatible = "variscite,var-som-imx7d-nand-wm8731-mx7customboard", + "variscite,var-som-imx7d", + "fsl,imx7d"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-emmc-mx7customboard.dts b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-emmc-mx7customboard.dts new file mode 100644 index 000000000000..1c419251bedd --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-emmc-mx7customboard.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * VAR-MX7CustomBoard for VAR-SOM-MX7 V2 with eMMC + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/dts-v1/; + +#include "imx7d-var-som.dtsi" +#include "imx7d-var-som-v2.dtsi" +#include "imx7d-var-som-emmc.dtsi" +#include "imx7d-var-som-wm8904.dtsi" +#include "imx7d-var-som-mx7customboard.dtsi" + +/ { + model = "Variscite VAR-SOM-MX7-5G_V2 with eMMC & WM8904 on VAR-MX7CustomBoard"; + compatible = "variscite,var-som-imx7d-v2-emmc-mx7customboard", + "variscite,var-som-imx7d-v2", + "fsl,imx7d"; +}; diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-nand-mx7customboard.dts b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-nand-mx7customboard.dts new file mode 100644 index 000000000000..68569111f3a3 --- /dev/null +++ b/arch/arm/boot/dts/nxp/imx/imx7d-var-som-v2-nand-mx7customboard.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * VAR-MX7CustomBoard for VAR-SOM-MX7 V2 with NAND + * + * Link: https://variscite.com/carrier-boards/var-mx7customboard/ + * + * Copyright (C) 2026 Variscite Ltd. - https://www.variscite.com/ + * + */ + +/dts-v1/; + +#include "imx7d-var-som.dtsi" +#include "imx7d-var-som-v2.dtsi" +#include "imx7d-var-som-nand.dtsi" +#include "imx7d-var-som-wm8904.dtsi" +#include "imx7d-var-som-mx7customboard.dtsi" + +/ { + model = "Variscite VAR-SOM-MX7-5G_V2 with NAND flash & WM8904 on VAR-MX7CustomBoard"; + compatible = "variscite,var-som-imx7d-v2-nand-mx7customboard", + "variscite,var-som-imx7d-v2", + "fsl,imx7d"; +}; -- cgit v1.2.3 From 3d0c54a7634f7a27527da4b83985509ce9d7619e Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:35 -0400 Subject: ARM: dts: imx51-zii-rdu1: rename node name i2c-gpio to i2c-0 The binding expects the node name to match the pattern '^i2c(@.+|-[a-z0-9]+)?$', but the node was named 'i2c-gpio' which conflicts with schema validation and produces: arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dtb: / (zii,imx51-rdu1): i2c-gpio: {'compatible': ['i2c-gpio'], 'pinctrl-names': ['default'], 'pinctrl-0': [[47]], 'sda-gpios': [[17, 2, 0]], 'scl-gpios': [[31, 4, 0]], 'i2c-gpio,delay-us': [50], 'status': ['okay'], '#address-cells': 1, '#size-cells': 0, 'codec@a': {'compatible': ['fsl,sgtl5000'], 'reg': [[10]], 'clocks': [[48]], 'VDDA-supply': [[49]], 'VDDIO-supply': [[50]], '#sound-dai-cells': 0, 'phandle': 57}} is not of type 'array' Rename the node to 'i2c-0' to fix above dtbs_check warning. Assisted-by: Claude:claude-sonnet-4.6 Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts b/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts index 91c63d1f2604..c17ab36474cd 100644 --- a/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts +++ b/arch/arm/boot/dts/nxp/imx/imx51-zii-rdu1.dts @@ -115,7 +115,7 @@ }; }; - i2c_gpio: i2c-gpio { + i2c_gpio: i2c-0 { compatible = "i2c-gpio"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_swi2c>; -- cgit v1.2.3 From a89327ced267f3bddd39bfef55697042ba24e4fb Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:36 -0400 Subject: ARM: dts: imx6qdl-emcon: Remove unrecognized disable-gpio PCIe property The 'disable-gpio' property is not defined in the fsl,imx6q-pcie binding schema and driver code, which causes the following dtbs_check warning: arch/arm/boot/dts/nxp/imx/imx6dl-emcon-avari.dtb: pcie@1ffc000 (fsl,imx6q-pcie): Unevaluated properties are not allowed ('disable-gpio' was unexpected) from schema $id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie.yaml Assisted-by: Claude:claude-sonnet-4.6 Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi index 9f4e746beb2d..34ad7fc04f6b 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-emcon.dtsi @@ -733,7 +733,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcie_ctrl>; reset-gpio = <&gpio7 12 GPIO_ACTIVE_LOW>; - disable-gpio = <&gpio2 22 GPIO_ACTIVE_LOW>; }; &pwm1 { -- cgit v1.2.3 From 5c2b3c0be9de935e232380f301a6b0ccc2e1654e Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:37 -0400 Subject: ARM: dts: imx7d-nitrogen7: drop unsupported wakeup-gpios from tsc2004 Remove undocumented and used property wakeup-gpios, which is the same as interrupts-extended. Fix below check_dtbs warning: arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dtb: touchscreen@48 (ti,tsc2004): 'wakeup-gpios' does not match any of the regexes: '^pinctrl-[0-9]+$' No known other user use wakeup-gpios. Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts b/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts index 2192f105ec81..c72859ac43e1 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-nitrogen7.dts @@ -284,7 +284,6 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c3_tsc2004>; interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>; - wakeup-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; }; }; -- cgit v1.2.3 From 8fdbfe040d08ed7d7c5e2dde2c16328ff29f086b Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:38 -0400 Subject: ARM: dts: imx7d-meerkat96: disable lcdif node The LCDIF node is enabled, but no display panel is connected through the required graph bindings. As a result, the LCDIF DT description is incomplete and triggers DT schema validation warnings. arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dtb: lcdif@30730000 (fsl,imx7d-lcdif): 'port' is a required propert Disable the LCDIF node until a proper panel node and display pipeline are added to fix above warnings. Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts b/arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts index f0fda15f3020..38f886c25509 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7d-meerkat96.dts @@ -134,7 +134,7 @@ &lcdif { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lcdif>; - status = "okay"; + status = "disabled"; }; &uart1 { -- cgit v1.2.3 From 4ca5ffee7500c3ce78fc821fa4eedfcb28e445a4 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:39 -0400 Subject: ARM: dts: imx50-kobo-aura: convert sd2_vmmc to regulator-fixed The sd2_vmmc regulator was using compatible = "regulator-gpio" with only a single state entry (states = <3300000 0>), which violates the gpio-regulator DT schema that requires at least two state pairs. Since the regulator operates at a fixed 3.3 V (regulator-min-microvolt equals regulator-max-microvolt), convert the node to regulator-fixed. Fix below check_dtbs warnings: arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dtb: gpio-regulator (regulator-gpio): states: [[3300000, 0]] is too short Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts b/arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts index 4725ee241cb1..4d8672ab1c42 100644 --- a/arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts +++ b/arch/arm/boot/dts/nxp/imx/imx50-kobo-aura.dts @@ -75,15 +75,14 @@ reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>; }; - sd2_vmmc: gpio-regulator { - compatible = "regulator-gpio"; + sd2_vmmc: regulator-sd2-vmmc { + compatible = "regulator-fixed"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sd2_vmmc>; regulator-name = "vmmc"; - states = <3300000 0>; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - enable-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>; + gpio = <&gpio4 12 GPIO_ACTIVE_LOW>; startup-delay-us = <100000>; }; }; -- cgit v1.2.3 From c9608f889d2e94888e980148ec04b77614448737 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:40 -0400 Subject: ARM: dts: imx6dl-b125v2: add touchscreen-size-x/y to exc80h60 node The eeti,exc3000 binding requires touchscreen-size-x and touchscreen-size-y properties. Add them for both the B125v2 and B125Pv2 boards, which use the AUO G121EAN01 panel at 1280x800 resolution. Fix below check_dtbs warnings: arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dtb: touchscreen@2a (eeti,exc80h60): 'touchscreen-size-x' is a required property Assisted-by: Claude:claude-sonnet-4.6 Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts | 2 ++ arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts index 94625d5d5918..c6ee5f9c8bf8 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-b125pv2.dts @@ -26,5 +26,7 @@ interrupt-parent = <&gpio5>; interrupts = <2 IRQ_TYPE_LEVEL_LOW>; reset-gpios = <&tca6424a 21 GPIO_ACTIVE_HIGH>; + touchscreen-size-x = <1280>; + touchscreen-size-y = <800>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts b/arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts index b3cfa8110ade..bd4ef091e412 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6dl-b125v2.dts @@ -26,5 +26,7 @@ interrupt-parent = <&gpio5>; interrupts = <2 IRQ_TYPE_LEVEL_LOW>; reset-gpios = <&tca6424a 21 GPIO_ACTIVE_HIGH>; + touchscreen-size-x = <1280>; + touchscreen-size-y = <800>; }; }; -- cgit v1.2.3 From 5e863f9f2c7f66a0ff902189c389d142bfdc0805 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:41 -0400 Subject: ARM: dts: imx6sll: remove unused node csi@20e8000 csi@20e8000 is never used with compatible string 'fsl,imx6s-csi'. Remove it to fix the below check_dtb warnings: arch/arm/boot/dts/nxp/imx/imx6sll-evk.dtb: /soc/bus@2000000/csi@20e8000: failed to match any schema with compatible: ['fsl,imx6sll-csi', 'fsl,imx6s-csi'] Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6sll.dtsi | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi index c96669605d1d..929f7815a454 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6sll.dtsi @@ -624,17 +624,6 @@ reg = <0x020e4000 0x4000>; }; - csi: csi@20e8000 { - compatible = "fsl,imx6sll-csi", "fsl,imx6s-csi"; - reg = <0x020e8000 0x4000>; - interrupts = ; - clocks = <&clks IMX6SLL_CLK_DUMMY>, - <&clks IMX6SLL_CLK_CSI>, - <&clks IMX6SLL_CLK_DUMMY>; - clock-names = "disp-axi", "csi_mclk", "disp_dcic"; - status = "disabled"; - }; - sdma: dma-controller@20ec000 { compatible = "fsl,imx6sll-sdma", "fsl,imx6ul-sdma"; reg = <0x020ec000 0x4000>; -- cgit v1.2.3 From 12f17efd282d8a66d5570098e12c1642efe2910a Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 1 Sep 2026 18:25:42 -0400 Subject: ARM: dts: imx6ul-14x14-evk: remove reduntant bus-type under csi node Remove reduntant undocument bus-type under csi node to fix below check_dtbs warnings: arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtb: csi@21c4000 (fsl,imx6ul-csi): port:endpoint: Unevaluated properties are not allowed ('bus-type' was unexpected) from schema $id: http://devicetree.org/schemas/media/nxp,imx7-csi.yaml buy-type already set at remote endpoint ov5640_to_parallel. Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi | 1 - 1 file changed, 1 deletion(-) 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 32afe4130e21..181676cd3b60 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi @@ -236,7 +236,6 @@ port { parallel_from_ov5640: endpoint { remote-endpoint = <&ov5640_to_parallel>; - bus-type = ; }; }; }; -- cgit v1.2.3 From 1fa2b2c7b7b8563161412be16880651e197d2bb6 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 2 Sep 2026 15:13:20 -0400 Subject: ARM: dts: imx53: drop fallback compatible "dlg,da9052" The "dlg,da9053-aa" compatible string is not compatible with "dlg,da9052". DA9052 vs DA9053-AA Differences (from da9052-regulator.c) 1. BUCK4 Voltage Range (only regulator table difference) DA9052 BUCK4 DA9053-AA BUCK4 Min voltage 1800 mV 950 mV Max voltage 3600 mV 2525 mV Step size 50 mV 25 mV DA9052 BUCK4 also has a non-linear voltage mapping above 3V (step increases to 100 mV for selector >= 24). DA9053-AA BUCK4 has no such special mapping. 2. BUCK Current Limits Level DA9052 (all BUCKs) DA9053-AA BUCK1 DA9053-AA BUCK2/3/4 0 700 mA 1600 mA 800 mA 1 800 mA 2000 mA 1000 mA 2 1000 mA 2400 mA 1200 mA 3 1200 mA 3000 mA 1500 mA DA9053-AA BUCK1 supports up to 3A (vs 1.2A on DA9052). Drop the fallback compatible to fix the following CHECK_DTBS warning: dialog@48 (dlg,da9053-aa): compatible: ['dlg,da9053-aa', 'dlg,da9052'] is too long Reviewed-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx53-qsb.dts | 2 +- arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx53-qsb.dts b/arch/arm/boot/dts/nxp/imx/imx53-qsb.dts index 6831836bd726..e7e15d2b82c4 100644 --- a/arch/arm/boot/dts/nxp/imx/imx53-qsb.dts +++ b/arch/arm/boot/dts/nxp/imx/imx53-qsb.dts @@ -13,7 +13,7 @@ &i2c1 { pmic: dialog@48 { - compatible = "dlg,da9053-aa", "dlg,da9052"; + compatible = "dlg,da9053-aa"; reg = <0x48>; interrupt-parent = <&gpio7>; interrupts = <11 IRQ_TYPE_LEVEL_LOW>; /* low-level active IRQ at GPIO7_11 */ diff --git a/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi b/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi index 6dc70a92d831..6eed683d92a8 100644 --- a/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx53-voipac-dmm-668.dtsi @@ -128,7 +128,7 @@ status = "okay"; pmic: dialog@48 { - compatible = "dlg,da9053-aa", "dlg,da9052"; + compatible = "dlg,da9053-aa"; reg = <0x48>; interrupt-parent = <&gpio7>; interrupts = <11 IRQ_TYPE_LEVEL_LOW>; /* low-level active IRQ at GPIO7_11 */ -- cgit v1.2.3 From a66939a238f9cd5f023eaa9e7cdb3078eaff640d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 9 Sep 2026 00:29:42 +0200 Subject: arm64: dts: imx8mm: imx8mp: Update EEPROM with nWP GPIO, label and layout Describe ID EEPROM nWP GPIO, label and nvmem layout. The i.MX8MM eDM SBC and i.MX8MP eDM SBC nvmem layout is almost identical, except for length of product-name@32 field, which is 19 Bytes on the Mini and 24 Bytes on the Plus. Signed-off-by: Marek Vasut Signed-off-by: Frank Li --- .../dts/freescale/imx8mm-data-modul-edm-sbc.dts | 56 +++++++++ .../dts/freescale/imx8mp-data-modul-edm-sbc.dts | 128 +++++++++++++++++++++ 2 files changed, 184 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts index df857de0375c..cb7647144043 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts @@ -431,7 +431,63 @@ eeprom: eeprom@50 { compatible = "atmel,24c32"; reg = <0x50>; + label = "dmo-board-info"; pagesize = <32>; + wp-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + company-name@24 { + reg = <0x24 0xd>; + }; + + product-name@32 { + reg = <0x32 0x13>; + }; + + board-revision@4b { + reg = <0x4b 0x3>; + }; + + serial-number@4f { + reg = <0x4f 0x8>; + }; + + manufacturing-date@70 { + reg = <0x70 0xa>; + }; + + test-date@7b { + reg = <0x7b 0xa>; + }; + + product-number@86 { + reg = <0x86 0x8>; + }; + + board-variant@9a { + reg = <0x9a 0x9>; + }; + + company-acronym@a4 { + reg = <0xa4 0x3>; + }; + + mac-address@b0 { + reg = <0xb0 0x6>; + }; + + board-id@100 { + reg = <0x100 0x4>; + }; + + wifi-id@120 { + reg = <0x120 0x4>; + }; + }; }; rtc: rtc@68 { diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts index c284edfa1f4c..4614a0de0790 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts +++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts @@ -421,14 +421,142 @@ eeprom900: eeprom@50 { /* board rev.900 */ compatible = "atmel,24c32"; reg = <0x50>; + label = "dmo-board-info"; pagesize = <32>; + wp-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>; status = "disabled"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + company-name@24 { + reg = <0x24 0xd>; + }; + + product-name@32 { + reg = <0x32 0x18>; + }; + + board-revision@4b { + reg = <0x4b 0x3>; + }; + + serial-number@4f { + reg = <0x4f 0x8>; + }; + + manufacturing-date@70 { + reg = <0x70 0xa>; + }; + + test-date@7b { + reg = <0x7b 0xa>; + }; + + product-number@86 { + reg = <0x86 0x8>; + }; + + board-variant@9a { + reg = <0x9a 0x9>; + }; + + company-acronym@a4 { + reg = <0xa4 0x3>; + }; + + eeprom900mac: mac-address@b0 { + reg = <0xb0 0x6>; + }; + + board-id@100 { + reg = <0x100 0x4>; + }; + + wifi-id@120 { + reg = <0x120 0x4>; + }; + + board-lvds-id@140 { + reg = <0x140 0x4>; + }; + + camera-id@160 { + reg = <0x160 0x4>; + }; + }; }; eeprom902: eeprom@51 { /* board rev.902 */ compatible = "atmel,24c32"; reg = <0x51>; + label = "dmo-board-info"; pagesize = <32>; + wp-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + company-name@24 { + reg = <0x24 0xd>; + }; + + product-name@32 { + reg = <0x32 0x18>; + }; + + board-revision@4b { + reg = <0x4b 0x3>; + }; + + serial-number@4f { + reg = <0x4f 0x8>; + }; + + manufacturing-date@70 { + reg = <0x70 0xa>; + }; + + test-date@7b { + reg = <0x7b 0xa>; + }; + + product-number@86 { + reg = <0x86 0x8>; + }; + + board-variant@9a { + reg = <0x9a 0x9>; + }; + + company-acronym@a4 { + reg = <0xa4 0x3>; + }; + + eeprom902mac: mac-address@b0 { + reg = <0xb0 0x6>; + }; + + board-id@100 { + reg = <0x100 0x4>; + }; + + wifi-id@120 { + reg = <0x120 0x4>; + }; + + board-lvds-id@140 { + reg = <0x140 0x4>; + }; + + camera-id@160 { + reg = <0x160 0x4>; + }; + }; }; rtc: rtc@68 { -- cgit v1.2.3 From af77a47c0cd2be48b0a76eae1c84a833ebbcef2d Mon Sep 17 00:00:00 2001 From: Franz Schnyder Date: Mon, 7 Sep 2026 08:47:20 +0200 Subject: arm64: dts: freescale: imx95-toradex-smarc: Add ENETC port 2 in SGMII mode The SMARC ETH2 uses the ENETC port 2 as a SGMII Ethernet interface. Enable the required support. Signed-off-by: Franz Schnyder Reviewed-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-toradex-smarc-dev.dts | 8 ++++++++ arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc-dev.dts b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc-dev.dts index 7437e523ff63..ffe537ccd5bd 100644 --- a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc-dev.dts +++ b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc-dev.dts @@ -64,6 +64,14 @@ status = "okay"; }; +/* SMARC SERDES_0 - ETH2 */ +&enetc_port2 { + phy-handle = <ðphy3>; + phy-mode = "sgmii"; + managed = "in-band-status"; + status = "okay"; +}; + /* SMARC CAN0 */ &flexcan1 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi index a6c5398a81e3..27ac9731733c 100644 --- a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi @@ -15,6 +15,7 @@ can1 = &flexcan2; ethernet0 = &enetc_port0; ethernet1 = &enetc_port1; + ethernet2 = &enetc_port2; mmc0 = &usdhc1; mmc1 = &usdhc2; mmc2 = &usdhc3; @@ -221,6 +222,12 @@ phy-mode = "rgmii-id"; }; +/* SMARC SERDES_0 */ +&enetc_port2 { + clocks = <&clk_serdes_eth_ref>; + clock-names = "ref"; +}; + /* SMARC CAN0 */ &flexcan1 { pinctrl-names = "default"; -- cgit v1.2.3 From 8476e5d51e47926983f6c4b774024746a57dad87 Mon Sep 17 00:00:00 2001 From: Franz Schnyder Date: Mon, 7 Sep 2026 08:47:21 +0200 Subject: arm64: dts: freescale: imx95-aquila: Add ENETC port 2 in SGMII mode The Aquila ETH_2 uses the ENETC port 2 as a SGMII Ethernet interface on the Development and Clover carrier board. Enable the required support. Signed-off-by: Franz Schnyder Reviewed-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts | 18 ++++++++++++++++++ arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts | 18 ++++++++++++++++++ arch/arm64/boot/dts/freescale/imx95-aquila.dtsi | 7 +++++++ 3 files changed, 43 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts b/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts index fd9304331446..365bce73eddd 100644 --- a/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts +++ b/arch/arm64/boot/dts/freescale/imx95-aquila-clover.dts @@ -67,6 +67,15 @@ status = "okay"; }; +/* Aquila ETH_2_XGMII */ +&enetc_port2 { + phy-handle = <ðphy2>; + phy-mode = "sgmii"; + managed = "in-band-status"; + + status = "okay"; +}; + /* Aquila CAN_1 */ &flexcan1 { status = "okay"; @@ -227,6 +236,15 @@ status = "okay"; }; +/* Aquila ETH_2_XGMII_MDIO, shared between all ethernet ports */ +&netc_emdio { + ethphy2: ethernet-phy@4 { + reg = <4>; + interrupt-parent = <&som_gpio_expander_1>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + }; +}; + /* Aquila PCIE_1 */ &pcie0 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts b/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts index 3df17700b632..7698ef44095c 100644 --- a/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts +++ b/arch/arm64/boot/dts/freescale/imx95-aquila-dev.dts @@ -104,6 +104,15 @@ status = "okay"; }; +/* Aquila ETH_2_XGMII */ +&enetc_port2 { + phy-handle = <ðphy2>; + phy-mode = "sgmii"; + managed = "in-band-status"; + + status = "okay"; +}; + /* Aquila CAN_1 */ &flexcan1 { status = "okay"; @@ -326,6 +335,15 @@ status = "okay"; }; +/* Aquila ETH_2_XGMII_MDIO, shared between all ethernet ports */ +&netc_emdio { + ethphy2: ethernet-phy@4 { + reg = <4>; + interrupt-parent = <&som_gpio_expander_1>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + }; +}; + /* Aquila PCIE_1 */ &pcie0 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi b/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi index 69dc962a24a1..f930965cb341 100644 --- a/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi @@ -16,6 +16,7 @@ can3 = &flexcan4; eeprom0 = &som_eeprom; ethernet0 = &enetc_port0; + ethernet1 = &enetc_port2; i2c0 = &lpi2c3; i2c1 = &lpi2c2; i2c2 = &i3c2; @@ -209,6 +210,12 @@ phy-mode = "rgmii-id"; }; +/* Aquila ETH_2_XGMII */ +&enetc_port2 { + clocks = <&clk_serdes_eth_ref>; + clock-names = "ref"; +}; + /* Aquila CAN_1 */ &flexcan1 { pinctrl-names = "default"; -- cgit v1.2.3 From e3631d0242842940f9e902afaea98202e56277e8 Mon Sep 17 00:00:00 2001 From: Linkai Gong Date: Thu, 13 Aug 2026 17:58:18 +0800 Subject: firmware: imx: dsp: fix mailbox channel leak on kasprintf failure If kasprintf() fails while setting up mailbox channels, already requested channels from earlier iterations were never freed. Route the failure through the existing cleanup path. Fixes: ffbf23d50353 ("firmware: imx: Add DSP IPC protocol interface") Signed-off-by: Linkai Gong Reviewed-by: Frank Li Signed-off-by: Frank Li --- drivers/firmware/imx/imx-dsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c index ed79e823157a..7e3f45ddf0c1 100644 --- a/drivers/firmware/imx/imx-dsp.c +++ b/drivers/firmware/imx/imx-dsp.c @@ -99,8 +99,10 @@ static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc) else chan_name = kasprintf(GFP_KERNEL, "rxdb%d", i - 2); - if (!chan_name) - return -ENOMEM; + if (!chan_name) { + ret = -ENOMEM; + goto out; + } dsp_chan = &dsp_ipc->chans[i]; dsp_chan->name = chan_name; -- cgit v1.2.3 From 478f68c644732750f8386e4de7c909c5ffb26ab2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 09:23:09 +0200 Subject: arm64: dts: imx95: Drop unsupported opp-hz-real in OPP tables There is no "opp-hz-real" property at all defined in the bindings and new DTS is not allowed to bring undocumented properties. Fix dtbs_check warnings like: imx95-15x15-evk-pcie0-ep.dtb: opp-500000000: opp-hz-real: b'\x00\x00\x00\x00\x1d\xcde\x00' is not of type 'object', 'integer', 'array', 'boolean', 'null' Signed-off-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95.dtsi | 3 --- arch/arm64/boot/dts/freescale/imx952.dtsi | 3 --- 2 files changed, 6 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi index 0f04d8bfcd88..d20c2498b9aa 100644 --- a/arch/arm64/boot/dts/freescale/imx95.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi @@ -255,19 +255,16 @@ opp-500000000 { opp-hz = /bits/ 64 <500000000>; - opp-hz-real = /bits/ 64 <500000000>; opp-microvolt = <920000>; }; opp-800000000 { opp-hz = /bits/ 64 <800000000>; - opp-hz-real = /bits/ 64 <800000000>; opp-microvolt = <920000>; }; opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; - opp-hz-real = /bits/ 64 <1000000000>; opp-microvolt = <920000>; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx952.dtsi b/arch/arm64/boot/dts/freescale/imx952.dtsi index 8702e9fdd255..1154b66dadb2 100644 --- a/arch/arm64/boot/dts/freescale/imx952.dtsi +++ b/arch/arm64/boot/dts/freescale/imx952.dtsi @@ -331,19 +331,16 @@ opp-500000000 { opp-hz = /bits/ 64 <500000000>; - opp-hz-real = /bits/ 64 <500000000>; opp-microvolt = <920000>; }; opp-800000000 { opp-hz = /bits/ 64 <800000000>; - opp-hz-real = /bits/ 64 <800000000>; opp-microvolt = <920000>; }; opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; - opp-hz-real = /bits/ 64 <1000000000>; opp-microvolt = <920000>; }; }; -- cgit v1.2.3 From 28cec01a2be2cf1e20aabd435f250f665ce24c8e Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Wed, 16 Sep 2026 10:40:22 +0200 Subject: arm64: dts: freescale: imx8mm-verdin-ivy: fix DIGI_1/DIGI_2 gpio-line-names gpio3's gpio-line-names names the two Ivy digital inputs "DIG_1" and "DIG_2", while the official Ivy Carrier Board datasheet (Section 2.10, Table 12) names them DIGI_1 and DIGI_2, matching the k3-am62-verdin-ivy.dtsi variant for the same carrier board pins. GPIO line names are meant to be stable across the whole Verdin family and its carrier boards, so userspace GPIO tooling that looks up a line by name works the same regardless of which Verdin SoM is fitted on Ivy. Fixes: adca46171ff7 ("arm64: dts: freescale: imx8mm-verdin: Add Ivy carrier board") Cc: stable@vger.kernel.org Link: https://docs.toradex.com/116799-ivy_carrier_board_datasheet.pdf Assisted-by: LLM Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi index 29075ff5eda6..b64751aa31d5 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin-ivy.dtsi @@ -270,8 +270,8 @@ "", "", "", - "DIG_1", /* SODIMM 56 */ - "DIG_2", /* SODIMM 58 */ + "DIGI_1", /* SODIMM 56 */ + "DIGI_2", /* SODIMM 58 */ "REL1", /* SODIMM 60 */ "REL2", /* SODIMM 62 */ "", /* 10 */ -- cgit v1.2.3 From cb45264c27fad31f7c58fbb1a5c2f7ec16018dae Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Wed, 16 Sep 2026 10:40:23 +0200 Subject: arm64: dts: freescale: imx8mp-verdin-ivy: fix DIGI_1/DIGI_2 gpio-line-names gpio3's gpio-line-names names the two Ivy digital inputs "DIG_1" and "DIG_2", while the official Ivy Carrier Board datasheet (Section 2.10, Table 12) names them DIGI_1 and DIGI_2, matching the k3-am62-verdin-ivy.dtsi variant for the same carrier board pins. GPIO line names are meant to be stable across the whole Verdin family and its carrier boards, so userspace GPIO tooling that looks up a line by name works the same regardless of which Verdin SoM is fitted on Ivy. Fixes: b98948b04295 ("arm64: dts: freescale: imx8mp-verdin: Add Ivy carrier board") Cc: stable@vger.kernel.org Link: https://docs.toradex.com/116799-ivy_carrier_board_datasheet.pdf Assisted-by: LLM Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi index db1b4ee7728c..bf021e85cfc9 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-ivy.dtsi @@ -333,8 +333,8 @@ "", "", "", - "DIG_1", /* SODIMM 56 */ - "DIG_2", /* SODIMM 58 */ + "DIGI_1", /* SODIMM 56 */ + "DIGI_2", /* SODIMM 58 */ "REL1", /* SODIMM 60 */ "REL2", /* SODIMM 62 */ "", /* 10 */ -- cgit v1.2.3 From 66a5b2bf9d217668ae683eecfaba38bcd61cfe94 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Tue, 15 Sep 2026 22:18:24 +0200 Subject: arm64: dts: freescale: imx95-aquila: fix gpio-line-names padding som_gpio_expander_1's gpio-line-names use "AQUILA_C1".."AQUILA_C4" instead of the zero-padded "AQUILA_C01".."AQUILA_C04" used by every other Cxx entry in this file and by k3-am69-aquila.dtsi, a different board implementing the same Aquila Family Specification. The zero-padded form is the official pin naming per the Aquila Family Specification and the Aquila iMX95 module datasheet. GPIO line names are meant to be stable across the whole Aquila family, so userspace GPIO tooling that looks up a line by name works the same on any Aquila SoM. Fixes: d5c082ba23db ("arm64: dts: freescale: add Aquila iMX95 support") Cc: stable@vger.kernel.org Link: https://docs.toradex.com/116801-aquila_family_specification.pdf Link: https://docs.toradex.com/117671-aquila_imx95_datasheet.pdf Assisted-by: LLM Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-aquila.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi b/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi index f930965cb341..c5f4cf0541f2 100644 --- a/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95-aquila.dtsi @@ -413,10 +413,10 @@ #gpio-cells = <2>; gpio-controller; gpio-line-names = - "AQUILA_C1", /* 0 */ - "AQUILA_C2", - "AQUILA_C3", - "AQUILA_C4", + "AQUILA_C01", /* 0 */ + "AQUILA_C02", + "AQUILA_C03", + "AQUILA_C04", "AQUILA_C36", "AQUILA_B74", "AQUILA_B75", -- cgit v1.2.3 From 90bc5a53c7f0733ec37a5c041b4e1aefa3d8d965 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Tue, 15 Sep 2026 22:14:10 +0200 Subject: arm64: dts: freescale: imx8mp-toradex-smarc: fix SMARC_SLEEP# gpio-line-names typo gpio3's gpio-line-names has "SLEEP#" instead of "SMARC_SLEEP#" for the SMARC SLEEP# connector signal, while the gpio-keys node driven by the very same GPIO line already labels it "SMARC_SLEEP#", and the imx95 Toradex SMARC variant names the equivalent line "SMARC_SLEEP#" too. GPIO line names are meant to be stable across the whole Toradex SMARC family, using the official SMARC-connector signal names from the SMARC specification and the SoM datasheet's pin assignment table, so userspace GPIO tooling that looks up a line by name works the same on any Toradex SMARC board. Fixes: 97dc91c04558 ("arm64: dts: freescale: add Toradex SMARC iMX8MP") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi index 0348da385f23..eb8b9db7e3cd 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi @@ -323,7 +323,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lvds_dsi_sel>; gpio-line-names = "ETH_0_INT#", /* 0 */ - "SLEEP#", + "SMARC_SLEEP#", "", "", "", -- cgit v1.2.3 From aa906abf611c7f37c0fe9171c1d33c40270aa5fe Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 14 Sep 2026 23:01:34 +0200 Subject: dt-bindings: vendor-prefixes: add Free Mobile Free Mobile is a French mobile network operator. Add its vendor prefix, used by the Nodebox v3 CPU Module (freemobile,nbxv3). Acked-by: Krzysztof Kozlowski Signed-off-by: Vincent Jardin Signed-off-by: Frank Li --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index ba2002969373..e467da45cd7a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -626,6 +626,8 @@ patternProperties: description: Freebox SAS "^freecom,.*": description: Freecom Gmbh + "^freemobile,.*": + description: Free Mobile "^frida,.*": description: Shenzhen Frida LCD Co., Ltd. "^friendlyarm,.*": -- cgit v1.2.3 From bd4912cb2e063f9b574732144fdc601043281281 Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 14 Sep 2026 23:01:35 +0200 Subject: dt-bindings: arm: fsl: add Free Mobile Nodebox v3 CPU Module Add DT compatible string for the Free Mobile Nodebox v3 CPU Module, an NXP LX2160A based board. Acked-by: Krzysztof Kozlowski Signed-off-by: Vincent Jardin Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index d200840c291e..c168b99c69a1 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1932,6 +1932,7 @@ properties: - description: LX2160A based Boards items: - enum: + - freemobile,nbxv3 - fsl,lx2160a-bluebox3 - fsl,lx2160a-bluebox3-rev-a - fsl,lx2160a-qds -- cgit v1.2.3 From 565b6713a460126874d15654fe24d995a57c822b Mon Sep 17 00:00:00 2001 From: Vincent Jardin Date: Mon, 14 Sep 2026 23:01:36 +0200 Subject: arm64: dts: freescale: add Nodebox v3 CPU Module The Nodebox v3 is a Free Mobile CPU module built around the NXP LX2160A (16x Cortex-A72, DPAA2). Signed-off-by: Vincent Jardin Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 2 + .../arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dts | 34 +++ .../boot/dts/freescale/fsl-lx2160a-nbxv3.dtsi | 330 +++++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dts create mode 100644 arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 7944e3b32513..2d8a0038214d 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -55,6 +55,8 @@ DTC_FLAGS_fsl-lx2160a-half-twins := -Wno-interrupt_map dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-half-twins.dtb DTC_FLAGS_fsl-lx2160a-honeycomb := -Wno-interrupt_map dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-honeycomb.dtb +DTC_FLAGS_fsl-lx2160a-nbxv3 := -Wno-interrupt_map +dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-nbxv3.dtb DTC_FLAGS_fsl-lx2160a-qds := -Wno-interrupt_map dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb DTC_FLAGS_fsl-lx2160a-rdb := -Wno-interrupt_map diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dts b/arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dts new file mode 100644 index 000000000000..cc02204e9d1b --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Free Mobile Nodebox v3 CPU Module (LX2160A) + * + * Copyright 2026 Free Mobile, Vincent Jardin + */ + +/dts-v1/; + +#include "fsl-lx2160a-rev2.dtsi" +#include "fsl-lx2160a-nbxv3.dtsi" + +/ { + compatible = "freemobile,nbxv3", "fsl,lx2160a"; + model = "Free Mobile Nodebox v3 CPU Module (LX2160A)"; +}; + +&fspi { + pinctrl-0 = <&fspi_dqs_sck_cs10_pins>, <&fspi_data30_pins>; + pinctrl-names = "default"; +}; + +&gpio1 { + pinctrl-0 = <&gpio1_31_28_pins>; + pinctrl-names = "default"; +}; + +&pcs_mdio13 { + status = "okay"; +}; + +&pcs_mdio14 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dtsi new file mode 100644 index 000000000000..9c5588a75cdd --- /dev/null +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-nbxv3.dtsi @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Free Mobile Nodebox v3 CPU Module (LX2160A) + * + * Copyright 2026 Free Mobile, Vincent Jardin + * + * This file is shared by the Linux kernel and U-Boot. + */ + +#include +#include + +/ { + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-restart { + compatible = "gpio-restart"; + gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + priority = <128>; + }; + + reg_ethsw_mdio: regulator-ethsw-mdio { + compatible = "regulator-fixed"; + gpio = <&gpio3 25 GPIO_ACTIVE_LOW>; + regulator-always-on; + regulator-boot-on; + regulator-name = "ethsw-mdio-en"; + }; +}; + +&crypto { + status = "okay"; +}; + +&dpmac13 { + phy-connection-type = "10gbase-r"; + phy-handle = <&lan8023_phy_s0>; + + status = "okay"; +}; + +&dpmac14 { + phy-connection-type = "10gbase-r"; + phy-handle = <&lan8023_phy_s1>; + + status = "okay"; +}; + +&dpmac17 { + phy-connection-type = "rgmii-id"; + phy-handle = <&rtl8211fd>; + + status = "okay"; +}; + +&dspi0 { + status = "okay"; + + dpll@0 { + compatible = "microchip,zl30733"; + reg = <0>; + spi-max-frequency = <12500000>; + }; +}; + +&dspi2 { + status = "okay"; +}; + +&emdio1 { + status = "okay"; + + /* Microchip LAN8023 dual 10G PCS/retimer, Clause 45 only, one address per slice */ + lan8023_phy_s0: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <2>; + }; + + lan8023_phy_s1: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <3>; + }; + + rtl8211fd: ethernet-phy@6 { + compatible = "ethernet-phy-id001c.c916"; + reg = <6>; + }; +}; + +&emdio2 { + status = "okay"; +}; + +&esdhc1 { + bus-width = <8>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + non-removable; + + status = "okay"; +}; + +&fsl_mc { + status = "okay"; +}; + +&fspi { + status = "okay"; + + /* GigaDevice GD55LB02GF, 256 MiB boot NOR */ + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>; + spi-max-frequency = <150000000>; + spi-rx-bus-width = <1>; + spi-tx-bus-width = <1>; + }; +}; + +&gpio0 { + gpio-line-names = + "", "", + "altfn:iic1-sda", "altfn:iic1-scl", + "altfn:uart4-sin", "altfn:uart4-sout", + "altfn:uart2-sin", "altfn:uart2-sout", + "altfn:uart3-sin", "altfn:uart3-sout", + "altfn:uart1-sin", "altfn:uart1-sout", + "altfn:spi3-pcs3", "altfn:spi3-pcs2", + "altfn:spi3-pcs1", "altfn:spi3-pcs0", + "altfn:spi1-sck", "altfn:spi1-sin", + "altfn:spi1-pcs2", "altfn:spi1-pcs1", + "altfn:spi1-pcs0", "altfn:spi1-sout", + "altfn:iic6-sda", "altfn:iic6-scl", + "altfn:spi3-sin", "altfn:spi3-sout", + "altfn:iic4-sda", "altfn:iic4-scl", + "altfn:iic3-sda", "altfn:iic3-scl", + "altfn:iic2-sda", "altfn:iic2-scl"; + + status = "okay"; +}; + +&gpio1 { + gpio-line-names = + "", "", "", "", "", "", + "cfg-rcw-src2", "cfg-rcw-src3", + "reset-req-b", + "altfn:sdhc2-clk", "altfn:sdhc2-ds", + "altfn:sdhc2-dat0", "altfn:sdhc2-dat1", + "altfn:sdhc2-dat2", "altfn:sdhc2-dat3", + "altfn:sdhc2-dat4", "altfn:sdhc2-dat5", + "altfn:sdhc2-dat6", "altfn:sdhc2-dat7", + "altfn:sdhc2-cmd", + "cfg-svr1", + "altfn:xspi1-cs0", "altfn:xspi1-sck", + "altfn:xspi1-dqs", + "altfn:xspi1-data0", "altfn:xspi1-data1", + "", "", + "flash-reset#", "pltrst#", "", "ethsw-reset#"; + + status = "okay"; + + /* Platform reset, no consumer node: released at boot */ + pltrst-hog { + gpio-hog; + gpios = <29 GPIO_ACTIVE_LOW>; + line-name = "pltrst#"; + output-low; + }; +}; + +&gpio2 { + gpio-line-names = + "lan8023-mdint", + "i2c2-alert#", "i2c4-alert#", "i2c6-alert#", + "u800-tca9539-int#", + "spi3-alert#", + "wake0", "wake1", + "carrier-hot#", + "u1300-rtl8211fd-int#", + "ethsw-int#", + "", "", + "u1700-zl30733-clk-gpio0", "u1700-zl30733-clk-gpio1", + "u1700-zl30733-clk-gpio2", "u1700-zl30733-clk-gpio3", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", ""; + + status = "okay"; +}; + +&gpio3 { + gpio-line-names = + "altfn:ec1-txd3", "altfn:ec1-txd2", + "altfn:ec1-txd1", "altfn:ec1-txd0", + "altfn:ec1-tx-en", "altfn:ec1-gtx-clk", + "altfn:ec1-rxd3", "altfn:ec1-rxd2", + "altfn:ec1-rxd1", "altfn:ec1-rxd0", + "altfn:ec1-rx-clk", "altfn:ec1-rx-dv", + "", "", + "ptp-refclk-in", + "", "", "", "", "", "", "", "", + "u1700-zl30733-pps-out", + "", + "ethsw-mdio-en", + "usb1-oc#", /* USB1_PWRFAULT and USB2_PWRFAULT pads: one wired-OR net */ + "", + "usb2-oc#", + "altfn:spi3-sck", + "", ""; + + status = "okay"; +}; + +/* On-module management bus */ +&i2c0 { + status = "okay"; + + /* +0V8_VDD core rail, MPS MPQ8646 (MPQ8785 core) over PMBus */ + vdd08: regulator@10 { + compatible = "mps,mpq8646"; + reg = <0x10>; + }; + + /* SO-DIMM SPD temperature sensors */ + temperature-sensor@18 { + compatible = "jedec,jc-42.4-temp"; + reg = <0x18>; + }; + + temperature-sensor@19 { + compatible = "jedec,jc-42.4-temp"; + reg = <0x19>; + }; + + eeprom@52 { + compatible = "atmel,24c32"; + reg = <0x52>; + pagesize = <32>; + }; + + /* Board ID straps */ + gpio@74 { + compatible = "ti,tca9539"; + reg = <0x74>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "boardid-0x0001", "boardid-0x0002", + "boardid-0x0004", "boardid-0x0008", + "boardid-0x0010", "boardid-0x0020", + "boardid-0x0040", "boardid-0x0080", + "boardid-0x0100", "boardid-0x0200", + "boardid-0x0400", "boardid-0x0800", + "boardid-0x1000", "boardid-0x2000", + "boardid-0x4000", "boardid-0x8000"; + }; + + u800: gpio@75 { + compatible = "ti,tca9539"; + reg = <0x75>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + gpio-line-names = + "carrier-gpio0", "carrier-gpio1", + "carrier-gpio2", "carrier-gpio3", + "carrier-gpio4", "carrier-gpio5", + "carrier-gpio6", "carrier-gpio7", + "carrier-gpio8", "carrier-gpio9", + "carrier-gpio10", "carrier-gpio11", + "", "", "", + "lan8023-rst"; + interrupt-controller; + interrupt-parent = <&gpio2>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&i2c1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; +}; + +&pcie3 { + status = "okay"; +}; + +&pcie4 { + status = "okay"; +}; + +&pcie5 { + status = "okay"; +}; + +&pcie6 { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; -- cgit v1.2.3 From f377ac5999a5d045168ddd25d204691c6653c06a Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Mon, 14 Sep 2026 20:39:31 +0200 Subject: arm64: dts: freescale: imx8mp-verdin-yavia: fix external GPIOs pinctrl_gpios_ext_yavia (SODIMM 64/66) is defined but never applied to gpio3, so those pins stay at their NAND reset function instead of GPIO. Fix SODIMM 64 to the correct pad, MX8MP_IOMUXC_NAND_READY_B (GPIO3_IO16). Fixes: b694fbe2ff40 ("arm64: dts: imx8mp-verdin: Add yavia carrier board") Cc: stable@vger.kernel.org Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi index f3d28e23ba6c..2a90f312fb27 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-yavia.dtsi @@ -117,6 +117,11 @@ status = "okay"; }; +&gpio3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpios_ext_yavia>; +}; + &gpio4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ctrl_sleep_moci>; @@ -266,7 +271,7 @@ pinctrl_gpios_ext_yavia: gpiosextyaviagrp { fsl,pins = < - MX8MP_IOMUXC_NAND_CE1_B__GPIO3_IO02 0x106 /* SODIMM 64 */ + MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x106 /* SODIMM 64 */ MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x106 /* SODIMM 66 */ >; }; -- cgit v1.2.3 From b91cb164517d6cfbccd8bedad11827d8ea3bcb97 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Mon, 14 Sep 2026 19:50:26 +0200 Subject: arm64: dts: freescale: imx95-toradex-smarc: enable Wi-Fi SD interface Enable usdhc3, used for the on-module u-blox MAYA-W260 Wi-Fi/BT module, it was left disabled by mistake in the initial commit. Fixes: 90bbe88e0ea6 ("arm64: dts: freescale: add Toradex SMARC iMX95") Cc: stable@vger.kernel.org Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi index 27ac9731733c..641573c9943e 100644 --- a/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi +++ b/arch/arm64/boot/dts/freescale/imx95-toradex-smarc.dtsi @@ -846,6 +846,7 @@ keep-power-in-suspend; non-removable; vmmc-supply = <®_wifi_en>; + status = "okay"; }; &scmi_bbm { -- cgit v1.2.3 From 8912bc10501ddb0d9b9ad450b21f42110b6bc619 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Mon, 14 Sep 2026 14:53:11 +0200 Subject: arm64: dts: imx95-var-dart-sonata: correct UART8 header pins Correct the UART8 header reference from J12 to J6 on the DART-MX95 Sonata carrier board. This is a documentation-only fix and does not change the hardware configuration. Co-developed-by: Natasha Kovalenko Signed-off-by: Natasha Kovalenko Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-var-dart-sonata.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-var-dart-sonata.dts b/arch/arm64/boot/dts/freescale/imx95-var-dart-sonata.dts index 3479abc25df2..9344a0d99418 100644 --- a/arch/arm64/boot/dts/freescale/imx95-var-dart-sonata.dts +++ b/arch/arm64/boot/dts/freescale/imx95-var-dart-sonata.dts @@ -336,7 +336,7 @@ status = "okay"; }; -/* Header (J12.4, J12.6) */ +/* Header (J6.4, J6.6) */ &lpuart8 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart8>; -- cgit v1.2.3 From fda9ea633a8d6d49f2165ec05016a769821da3b3 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Mon, 14 Sep 2026 15:46:12 +0200 Subject: arm64: dts: imx93-kontron: Adjust GPIO4_IO29 usage Early prototypes had GPIO4_IO29 control the CARRIER_PWR_EN signal. This is now controlled by hardware and the GPIO4_IO29 is routed to the GPIO_B_2 OSM pad. Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- .../boot/dts/freescale/imx93-kontron-osm-s.dtsi | 32 ++-------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi b/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi index f881912cde46..36548d918169 100644 --- a/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi @@ -34,29 +34,6 @@ regulator-max-microvolt = <3300000>; regulator-name = "VCC_SDIO_A"; }; - - reg_vdd_carrier: regulator-vdd-carrier { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reg_vdd_carrier>; - gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>; - enable-active-high; - regulator-always-on; - regulator-boot-on; - regulator-name = "VDD_CARRIER"; - - regulator-state-standby { - regulator-on-in-suspend; - }; - - regulator-state-mem { - regulator-off-in-suspend; - }; - - regulator-state-disk { - regulator-off-in-suspend; - }; - }; }; &flexcan1 { /* OSM-S CAN_A */ @@ -113,7 +90,7 @@ "ETH_A_TXD3", "ETH_A_TXD2", "ETH_A_TXD1", "ETH_A_TXD0", "ETH_A_TX_EN", "ETH_A_TX_CLK", "ETH_A_RX_CTL", "ETH_A_RX_CLK", "ETH_A_RXD0", "ETH_A_RXD1", "ETH_A_RXD2", "ETH_A_RXD3", - "GPIO_B_0", "CARRIER_PWR_EN"; + "GPIO_B_0", "GPIO_B_2"; }; &lpi2c1 { @@ -385,6 +362,7 @@ pinctrl_gpio4: gpio4grp { fsl,pins = < MX93_PAD_CCM_CLKO3__GPIO4_IO28 0x31e /* GPIO_B_0 */ + MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x31e /* GPIO_B_2 */ >; }; @@ -465,12 +443,6 @@ >; }; - pinctrl_reg_vdd_carrier: regvddcarriergrp { - fsl,pins = < - MX93_PAD_CCM_CLKO4__GPIO4_IO29 0x31e /* CARRIER_PWR_EN */ - >; - }; - pinctrl_rtc: rtcgrp { fsl,pins = < MX93_PAD_SD2_VSELECT__GPIO3_IO19 0x31e -- cgit v1.2.3 From ae6f4e9b6466586f135ea238da2b6af499bd4060 Mon Sep 17 00:00:00 2001 From: Oualid Derouiche Date: Mon, 14 Sep 2026 15:46:13 +0200 Subject: arm64: dts: imx93-kontron: Make USB-C connector "device-only" The dual-role support was broken on early prototypes and has been removed in later hardware revisions. Reflect that by setting dr_mode to "peripheral" and removing properties related to dual-role usage. Signed-off-by: Oualid Derouiche Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts b/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts index 4620c070f4d7..0277640d7c4c 100644 --- a/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts +++ b/arch/arm64/boot/dts/freescale/imx93-kontron-bl-osm-s.dts @@ -158,12 +158,8 @@ }; &usbotg1 { - adp-disable; - hnp-disable; - srp-disable; disable-over-current; - dr_mode = "otg"; - usb-role-switch; + dr_mode = "peripheral"; status = "okay"; }; -- cgit v1.2.3 From ed7c97953012ab2bd025fd93fb86dc233456c7fc Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Mon, 14 Sep 2026 15:46:14 +0200 Subject: arm64: dts: imx8mm-kontron: Describe the ethernet PHY LEDs The RJ45 of the BL i.MX8MM has two LEDs wired to LED0 and LED1 of the VSC8531 PHY. Describe them using the standard LED subnodes of the ethernet PHY binding, so that they show up as LED class devices and can be driven by the netdev trigger. Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts index dd59af0ebaae..1f3d0577f10c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts @@ -5,6 +5,7 @@ /dts-v1/; +#include #include "imx8mm-kontron-sl.dtsi" / { @@ -139,6 +140,25 @@ reset-assert-us = <1>; reset-deassert-us = <15000>; reset-gpios = <&gpio4 27 GPIO_ACTIVE_LOW>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + linux,default-trigger = "netdev"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + linux,default-trigger = "netdev"; + }; + }; }; }; }; -- cgit v1.2.3 From b24194da984a3351cf0e01dfaed95fd753a52098 Mon Sep 17 00:00:00 2001 From: Oualid Derouiche Date: Mon, 14 Sep 2026 15:46:15 +0200 Subject: arm64: dts: imx8mm-kontron: Add GPIO labels and comments Describe the GPIOs and their purpose using labels and comments. Signed-off-by: Oualid Derouiche Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- .../arm64/boot/dts/freescale/imx8mm-kontron-bl.dts | 81 +++++++++++++++------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts index 1f3d0577f10c..72588af057d2 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts @@ -97,6 +97,7 @@ }; }; +/* CAN */ &ecspi2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi2>; @@ -124,6 +125,7 @@ status = "okay"; }; +/* ETH0 */ &fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet>; @@ -163,9 +165,24 @@ }; }; +/* DIO */ +&gpio1 { + gpio-line-names = "", "", "", "DOUT1", + "", "", "DIN1", "DOUT2", + "DIN2", "DOUT3", "DIN3", "DOUT4"; +}; + &gpio4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio4>; + gpio-line-names = "", "CAN_ADR0", "", "", + "CAN_ADR1", "CAN_ADR2", "CAN_ADR3", "LED6", + "LED4", "LED5", "", "", + "", "", "DSI_MUX_SEL", "DSI_MUX_OE", + "HDMI_IRQ", "LED1", "LED3", "LED2", + "", "", "", "", + "", "ETH_IRQ", "LVDS_EN", "PHY_RST", + "CAN_IRQ", "UART2_RTS"; dsi_mux_sel_hdmi: dsi-mux-sel-hdmi-hog { gpio-hog; @@ -190,6 +207,10 @@ }; }; +&gpio5 { + gpio-line-names = "", "", "DIN4"; +}; + &i2c3 { clock-frequency = <400000>; pinctrl-names = "default"; @@ -274,6 +295,7 @@ status = "okay"; }; +/* RS232 */ &uart1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1>; @@ -281,6 +303,7 @@ status = "okay"; }; +/* RS485 */ &uart2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2>; @@ -324,6 +347,7 @@ }; }; +/* SD-card */ &usdhc2 { pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc2>; @@ -341,13 +365,13 @@ pinctrl_adv7535: adv7535grp { fsl,pins = < - MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x19 + MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x19 /* HDMI_IRQ */ >; }; pinctrl_can: cangrp { fsl,pins = < - MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x19 + MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x19 /* CAN_IRQ */ >; }; @@ -356,7 +380,7 @@ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x82 MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x82 MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x82 - MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x19 + MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x19 /* ECSPI2_CS1 */ >; }; @@ -365,7 +389,7 @@ MX8MM_IOMUXC_UART2_RXD_ECSPI3_MISO 0x82 MX8MM_IOMUXC_UART1_TXD_ECSPI3_MOSI 0x82 MX8MM_IOMUXC_UART1_RXD_ECSPI3_SCLK 0x82 - MX8MM_IOMUXC_UART2_TXD_GPIO5_IO25 0x19 + MX8MM_IOMUXC_UART2_TXD_GPIO5_IO25 0x19 /* ECSPI3_CS1 */ >; }; @@ -385,40 +409,45 @@ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f - MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x19 /* PHY RST */ - MX8MM_IOMUXC_SAI2_TXC_GPIO4_IO25 0x19 /* ETH IRQ */ + MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x19 /* PHY_RST */ + MX8MM_IOMUXC_SAI2_TXC_GPIO4_IO25 0x19 /* ETH_IRQ */ >; }; pinctrl_gpio_led: gpioledgrp { fsl,pins = < MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16 0x19 - MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x19 - MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x19 - MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x19 - MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x19 - MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x19 - MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x19 + MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x19 /* LED6 */ + MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x19 /* LED4 */ + MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x19 /* LED5 */ + MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x19 /* LED1 */ + MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x19 /* LED3 */ + MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x19 /* LED2 */ >; }; pinctrl_gpio: gpiogrp { fsl,pins = < - MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x19 - MX8MM_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19 - MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 - MX8MM_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x19 - MX8MM_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x19 - MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x19 - MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 - MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2 0x19 + MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x19 /* DOUT1 */ + MX8MM_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x19 /* DIN1 */ + MX8MM_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19 /* DOUT2 */ + MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x19 /* DIN2 */ + MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 /* DOUT3 */ + MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* DIN3 */ + MX8MM_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x19 /* DOUT4 */ + MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2 0x19 /* DIN4 */ >; }; pinctrl_gpio4: gpio4grp { fsl,pins = < - MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x19 - MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x19 + /* CAN address DIP switches 1-4 */ + MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x19 /* CAN_ADR0 */ + MX8MM_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x19 /* CAN_ADR1 */ + MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x19 /* CAN_ADR2 */ + MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6 0x19 /* CAN_ADR3 */ + MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x19 /* DSI_MUX_SEL */ + MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x19 /* DSI_MUX_OE */ >; }; @@ -444,7 +473,7 @@ pinctrl_sn65dsi84: sn65dsi84grp { fsl,pins = < - MX8MM_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x19 + MX8MM_IOMUXC_SAI2_TXD0_GPIO4_IO26 0x19 /* LVDS_EN */ MX8MM_IOMUXC_SD2_WP_GPIO2_IO20 0x19 >; }; @@ -463,13 +492,13 @@ MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX 0x0 MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX 0x0 MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x0 - MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19 + MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29 0x19 /* UART2_RTS */ >; }; pinctrl_usb_eth2: usbeth2grp { fsl,pins = < - MX8MM_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x19 + MX8MM_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x19 /* ETH_RST */ >; }; @@ -481,7 +510,7 @@ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0 MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0 MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0 - MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19 + MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19 /* SD2_CD */ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0 >; }; -- cgit v1.2.3 From 8d82d1419bc0e1ca1de86a58f07f377eb0a4f31f Mon Sep 17 00:00:00 2001 From: Oualid Derouiche Date: Mon, 14 Sep 2026 15:46:16 +0200 Subject: arm64: dts: imx8mm-kontron: Add SPI EERAM on BL device Board revision 2 has an EERAM chip populated. Add support for it. Signed-off-by: Oualid Derouiche Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts index 72588af057d2..27bfad56dbe8 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts +++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts @@ -123,6 +123,12 @@ pinctrl-0 = <&pinctrl_ecspi3>; cs-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>; status = "okay"; + + eeram@0 { + compatible = "microchip,48l640"; + reg = <0>; + spi-max-frequency = <20000000>; + }; }; /* ETH0 */ -- cgit v1.2.3 From a5f316e602d3f5852fe2f88226fe64c8a495f479 Mon Sep 17 00:00:00 2001 From: Oualid Derouiche Date: Mon, 14 Sep 2026 15:46:17 +0200 Subject: arm64: dts: imx8mp-kontron: Fix LVDS clock frequency for DL device The panel needs a pixel clock of 50 MHz, which means the LDB serializer has to run at 50 MHz * 7 = 350 MHz. The LDB rate itself is set by the fsl-ldb driver, but VIDEO_PLL1 needs to be pinned to 700 MHz, so that both the LDB clock (/2) and the pixel clock (/14) can be derived from it exactly. Fixes: 946ab10e3f40 ("arm64: dts: Add support for Kontron OSM-S i.MX8MP SoM and BL carrier board") Signed-off-by: Oualid Derouiche Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso b/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso index 41a2bb74f156..88b30ca66adf 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso +++ b/arch/arm64/boot/dts/freescale/imx8mp-kontron-dl.dtso @@ -6,6 +6,7 @@ /dts-v1/; /plugin/; +#include #include #include #include "imx8mp-pinfunc.h" @@ -99,6 +100,16 @@ &lvds_bridge { status = "okay"; + /* + * The video PLL clock frequency needs to be configured manually. + * The panel needs a LVDS clock of 50 MHz * 7 = 350 MHz. + * IMX8MP_CLK_MEDIA_LDB = IMX8MP_CLK_MEDIA_DISP2_PIX * 7 + * IMX8MP_VIDEO_PLL1 = IMX8MP_CLK_MEDIA_LDB * 2 + */ + assigned-clocks = <&clk IMX8MP_CLK_MEDIA_LDB>, + <&clk IMX8MP_VIDEO_PLL1>; + assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>; + assigned-clock-rates = <0>, <700000000>; }; /* redefine to remove touch controller GPIOs */ -- cgit v1.2.3 From b2e2c41c398d6aa097203e70c7acf82ba4c5a6a0 Mon Sep 17 00:00:00 2001 From: Eberhard Stoll Date: Mon, 14 Sep 2026 15:46:09 +0200 Subject: ARM: dts: imx6ul-kontron-bl-common: Replace UART3 with DIP switch GPIOs The latest board revision has DIP switches and lacks UART3 instead. As the old revision has long been deprecated and not maintained anymore, drop the support and reflect the current state of the hardware. As the old revision hasn't been widely used and UART3 was only available through an obscure extension connector, no users are expected to be affected by this change. Signed-off-by: Eberhard Stoll Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- .../boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi index f4c45e964daf..a71669bef7d4 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi @@ -172,13 +172,6 @@ status = "okay"; }; -&uart3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart3>; - uart-has-rtscts; - status = "okay"; -}; - &uart4 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart4>; @@ -283,6 +276,11 @@ MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x1b0b0 /* DIN1 */ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x1b0b0 /* DOUT2 */ MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00 0x1b0b0 /* DIN2 */ + + MX6UL_PAD_UART3_TX_DATA__GPIO1_IO24 0x1b0b0 /* CAN_ADR0 (DIP sw 1) */ + MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25 0x1b0b0 /* CAN_ADR1 (DIP sw 2) */ + MX6UL_PAD_UART3_CTS_B__GPIO1_IO26 0x1b0b0 /* CAN_ADR2 (DIP sw 3) */ + MX6UL_PAD_UART3_RTS_B__GPIO1_IO27 0x1b0b0 /* CAN_ADR3 (DIP sw 4) */ >; }; @@ -334,15 +332,6 @@ >; }; - pinctrl_uart3: uart3grp { - fsl,pins = < - MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0x1b0b1 - MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0x1b0b1 - MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS 0x1b0b1 - MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS 0x1b0b1 - >; - }; - pinctrl_uart4: uart4grp { fsl,pins = < MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX 0x1b0b1 -- cgit v1.2.3 From 27408de30b6e5bb93dfb99af508a670abd787b00 Mon Sep 17 00:00:00 2001 From: Oualid Derouiche Date: Mon, 14 Sep 2026 15:46:10 +0200 Subject: ARM: dts: imx6ul-kontron-bl-common: Add GPIO labels Describe the GPIOs and their purpose using labels. Signed-off-by: Oualid Derouiche Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi index a71669bef7d4..65c5f4450c36 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi @@ -132,6 +132,22 @@ }; }; +&gpio1 { + gpio-line-names = "", "", "ADC_REF", "AIN1", + "", "", "ENET2_MDIO", "ENET2_MDC", + "AIN2", "", "", "", + "", "", "", "", + "", "", "", "SD1_CD", + "", "", "", "", + "CAN_ADR0", "CAN_ADR1", "CAN_ADR2", "CAN_ADR3", + "", "", "LED_H14"; +}; + +&gpio5 { + gpio-line-names = "DIN2", "DOUT2", "LED_H16", + "LED_H15", "DIN1", "DOUT1"; +}; + &i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; -- cgit v1.2.3 From d3b1ebe5a7a1f345fdc75a657ae725af0a0bbdbd Mon Sep 17 00:00:00 2001 From: Oualid Derouiche Date: Mon, 14 Sep 2026 15:46:11 +0200 Subject: ARM: dts: imx6ul-kontron-bl-common: Fix USB OTG1 ID pin configuration Add the missing MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID pinmux entry so the USB OTG ID pin is correctly routed and OTG can be used. Signed-off-by: Oualid Derouiche Signed-off-by: Frieder Schrempf Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi index 65c5f4450c36..0658584c9f11 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi @@ -357,6 +357,7 @@ pinctrl_usbotg1: usbotg1grp { fsl,pins = < + MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x17059 MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x1b0b0 >; }; -- cgit v1.2.3 From 92fd18d609ff13e27ab9d19c4764633acde593ec Mon Sep 17 00:00:00 2001 From: Joy Zou Date: Mon, 14 Sep 2026 11:21:07 +0800 Subject: arm64: dts: imx91-evk/qsb: add rtc1 alias for external PCF2131 RTC Only rtc0 was aliased to bbnsm_rtc, while the external pcf2131 had no fixed index. When both drivers are modules, the pcf2131 may register first and take rtc0, pushing bbnsm_rtc to rtc1. Since suspend/resume wakeup relies on the internal bbnsm RTC at rtc0, this broke wakeup. Add rtc1 alias for the pcf2131 on imx91-11x11-evk and imx91-9x9-qsb, so it keeps a fixed index while bbnsm_rtc stays rtc0. Signed-off-by: Joy Zou Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts | 1 + arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts index 6ccb942786c3..66466ce001ca 100644 --- a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts @@ -25,6 +25,7 @@ mmc1 = &usdhc2; mmc2 = &usdhc3; rtc0 = &bbnsm_rtc; + rtc1 = &pcf2131; serial0 = &lpuart1; serial1 = &lpuart2; serial2 = &lpuart3; diff --git a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts index f1ed7983226b..b7f0e39b867a 100644 --- a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts +++ b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts @@ -23,6 +23,7 @@ mmc0 = &usdhc1; mmc1 = &usdhc2; rtc0 = &bbnsm_rtc; + rtc1 = &pcf2131; serial0 = &lpuart1; }; -- cgit v1.2.3 From fa7d47a05b464c5ec3af39ebd06b8b73abaa42ff Mon Sep 17 00:00:00 2001 From: Joy Zou Date: Mon, 14 Sep 2026 11:21:08 +0800 Subject: arm64: dts: imx93-evk/qsb: add rtc1 alias for external PCF2131 RTC Only rtc0 was aliased to bbnsm_rtc, while the external pcf2131 had no fixed index. When both drivers are modules, the pcf2131 may register first and take rtc0, pushing bbnsm_rtc to rtc1. Since suspend/resume wakeup relies on the internal bbnsm RTC at rtc0, this broke wakeup. Add rtc1 alias for the pcf2131 on imx93-11x11-evk and imx93-9x9-qsb, so it keeps a fixed index while bbnsm_rtc stays rtc0. Signed-off-by: Joy Zou Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi | 1 + arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi index f48e7947cf64..2f3f9ebd3345 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi @@ -18,6 +18,7 @@ mmc0 = &usdhc1; mmc1 = &usdhc2; rtc0 = &bbnsm_rtc; + rtc1 = &pcf2131; serial0 = &lpuart1; serial1 = &lpuart2; serial2 = &lpuart3; diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts index 01c11c517986..4e31a78963fe 100644 --- a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts +++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts @@ -28,6 +28,7 @@ mmc0 = &usdhc1; mmc1 = &usdhc2; rtc0 = &bbnsm_rtc; + rtc1 = &pcf2131; serial0 = &lpuart1; serial1 = &lpuart2; serial2 = &lpuart3; @@ -306,7 +307,7 @@ }; }; - rtc@53 { + pcf2131: rtc@53 { compatible = "nxp,pcf2131"; reg = <0x53>; interrupt-parent = <&pcal6524>; -- cgit v1.2.3 From c926063088debfa61147918c473831896ecbc233 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Fri, 11 Sep 2026 15:44:09 +0200 Subject: ARM: dts: imx7-colibri-iris-v2: drop no-op delete-property usdhc1 never has a "keep-power-in-suspend" property set anywhere in its inheritance chain, so this /delete-property/ is a no-op left over since it was introduced. Signed-off-by: Francesco Dolcini Assisted-by: LLM Signed-off-by: Frank Li --- arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi index b687727f956a..216dac7823df 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-colibri-iris-v2.dtsi @@ -106,7 +106,6 @@ /* Colibri MMC/SD, UHS-I capable uSD slot */ &usdhc1 { cap-power-off-card; - /delete-property/ keep-power-in-suspend; /delete-property/ no-1-8-v; vmmc-supply = <®_3v3_vmmc>; status = "okay"; -- cgit v1.2.3 From 262e301dfa27dbd66d95170f929e97afcd517364 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 17 Sep 2026 10:58:01 -0400 Subject: arm64: dts: imx8qm-ss-conn: add #phy-cells for usbphynop2 Add required property #phy-cells for usbphynop2 to fix below CHECK_DTBS warnings: arch/arm64/boot/dts/freescale/imx8qm-apalis-eval-v1.2.dtb: usbphynop2 (usb-nop-xceiv): '#phy-cells' is a required property from schema $id: http://devicetree.org/schemas/usb/usb-nop-xceiv.yaml Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi index c7063aaac4a3..61c73e701b10 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi @@ -9,6 +9,7 @@ compatible = "usb-nop-xceiv"; clocks = <&usb2_lpcg IMX_LPCG_CLK_7>; clock-names = "main_clk"; + #phy-cells = <0>; power-domains = <&pd IMX_SC_R_USB_0_PHY>; status = "disabled"; }; -- cgit v1.2.3 From e0a7a6e9dd2e434251e4672900521ff43cdeeb30 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 17 Sep 2026 10:58:02 -0400 Subject: arm64: dts: imx8qm-ss-conn: update usbphynop2's power-domain to IMX_SC_R_USB_1_PHY usbphynop2 is used by usbh1: usb@5b0e0000. Replace IMX_SC_R_USB_0_PHY with IMX_SC_R_USB_1_PHY to fix typo. Fixes: bc2f1c482286f ("arm64: dts: imx8qm-ss-conn: Add HSIC usb@5b0e0000 node") Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi index 61c73e701b10..f25f62d51f69 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-conn.dtsi @@ -10,7 +10,7 @@ clocks = <&usb2_lpcg IMX_LPCG_CLK_7>; clock-names = "main_clk"; #phy-cells = <0>; - power-domains = <&pd IMX_SC_R_USB_0_PHY>; + power-domains = <&pd IMX_SC_R_USB_1_PHY>; status = "disabled"; }; }; -- cgit v1.2.3 From 4fed69596d776c1361150839acb9e089aaa0116e Mon Sep 17 00:00:00 2001 From: Antoine Gouby Date: Thu, 17 Sep 2026 12:20:08 +0200 Subject: dt-bindings: arm: fsl: Add Toradex OSM iMX95 Add Toradex OSM iMX95 SoM and the Toradex OSM development carrier board it can be combined with. The Toradex OSM iMX95 is a SoM compliant with the OSM V1.2 specification from SGET using the NXP i.MX95 SoC and is available in Size L (45x45 mm). Link: https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx95 Signed-off-by: Antoine Gouby Signed-off-by: Francesco Dolcini Acked-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index c168b99c69a1..e16fe1ec7026 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1561,6 +1561,12 @@ properties: - const: toradex,aquila-imx95 # Aquila iMX95 Module - const: fsl,imx95 + - description: Toradex Boards with OSM iMX95 Modules + items: + - const: toradex,osm-imx95-dev # Toradex OSM iMX95 Module on Toradex OSM Development Board + - const: toradex,osm-imx95 # Toradex OSM iMX95 Module + - const: fsl,imx95 + - description: Toradex Boards with SMARC iMX95 Modules items: - const: toradex,smarc-imx95-dev # Toradex SMARC iMX95 on Toradex SMARC Development Board -- cgit v1.2.3 From 39be5a7e3ecc08098c039561237499aa595700da Mon Sep 17 00:00:00 2001 From: Antoine Gouby Date: Thu, 17 Sep 2026 12:20:09 +0200 Subject: arm64: dts: freescale: Add Toradex OSM iMX95 Add support for the Toradex OSM iMX95 SoM, based on an NXP i.MX95 SoC, and its OSM development carrier board. Link: https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx95 Link: https://www.toradex.com/products/carrier-board/osm-development-board Co-developed-by: Franz Schnyder Signed-off-by: Franz Schnyder Signed-off-by: Antoine Gouby Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../boot/dts/freescale/imx95-toradex-osm-dev.dts | 404 ++++++++ .../boot/dts/freescale/imx95-toradex-osm.dtsi | 1032 ++++++++++++++++++++ 3 files changed, 1437 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx95-toradex-osm-dev.dts create mode 100644 arch/arm64/boot/dts/freescale/imx95-toradex-osm.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 2d8a0038214d..9971b34f7301 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -957,6 +957,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-sof.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-frdm-pro.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-clover.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-dev.dtb +dtb-$(CONFIG_ARCH_MXC) += imx95-toradex-osm-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-toradex-smarc-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596la-mba95xxca.dtb dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596sa-mb-smarc-2.dtb diff --git a/arch/arm64/boot/dts/freescale/imx95-toradex-osm-dev.dts b/arch/arm64/boot/dts/freescale/imx95-toradex-osm-dev.dts new file mode 100644 index 000000000000..b3d54be07c43 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx95-toradex-osm-dev.dts @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx95 + * https://www.toradex.com/products/carrier-board/osm-development-board + */ + +/dts-v1/; + +#include +#include +#include +#include "imx95-toradex-osm.dtsi" + +/ { + model = "Toradex OSM iMX95 on OSM Development Board"; + compatible = "toradex,osm-imx95-dev", + "toradex,osm-imx95", + "fsl,imx95"; + + aliases { + eeprom1 = &carrier_eeprom; + }; + + reg_carrier_1p8v: regulator-carrier-1p8v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "On-carrier 1V8"; + }; + + sfp: sfp { + compatible = "sff,sfp"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_b0>, <&pinctrl_gpio_b1>, + <&pinctrl_gpio_b2>, <&pinctrl_gpio_b3>; + i2c-bus = <&i2c_mux_carrier_sfp>; + los-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + mod-def0-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + rate-select0-gpios = <&som_gpio_expander_0 4 GPIO_ACTIVE_HIGH>; + rate-select1-gpios = <&som_gpio_expander_1 3 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&gpio5 11 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>; + }; + + 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 = "verdin-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"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Line", "Line In Jack"; + + codec_dai: simple-audio-card,codec { + clocks = <&scmi_clk IMX95_CLK_SAI3>; + sound-dai = <&wm8904_1a>; + }; + + simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + }; +}; + +/* OSM ADC_0, ADC_1 */ +&adc1 { + status = "okay"; +}; + +/* OSM ETH_A */ +&enetc_port0 { + phy-handle = <ðphy_a>; + phy-mode = "rgmii-id"; + + status = "okay"; +}; + +/* OSM ETH_B */ +&enetc_port1 { + phy-handle = <ðphy_b>; + phy-mode = "rgmii-id"; + + status = "okay"; +}; + +/* OSM ETH_C */ +&enetc_port2 { + managed = "in-band-status"; + phy-mode = "10gbase-r"; + sfp = <&sfp>; + + status = "okay"; +}; + +/* OSM CAN_A */ +&flexcan2 { + status = "okay"; +}; + +/* OSM CAN_B */ +&flexcan3 { + status = "okay"; +}; + +&gpio5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a1>, <&pinctrl_gpio_a2>, <&pinctrl_gpio_a3>, + <&pinctrl_gpio_a4>, <&pinctrl_gpio_a5>, <&pinctrl_gpio_a6>; +}; + +/* OSM I2C_A */ +&lpi2c1 { + status = "okay"; + + fan_controller: fan-controller@19 { + compatible = "ti,amc6821"; + reg = <0x19>; + #pwm-cells = <2>; + + fan { + cooling-levels = <255>; + pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED>; + }; + }; + + wm8904_1a: audio-codec@1a { + compatible = "wlf,wm8904"; + reg = <0x1a>; + clocks = <&scmi_clk IMX95_CLK_SAI3>; + 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>; + }; + + gpio@20 { + compatible = "nxp,pcal6408"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "PWR_CTRL_CAN_A", /* 0 */ + "PWR_CTRL_CAN_B", + "PWR_CTRL_USB-HUB", + "LVDS_MUX_CTRL", + "USB_MUX_CTRL", + "I2CA_IOEXP_P5", + "I2CA_IOEXP_P6", + "I2CA_IOEXP_P7"; + + lvds_mux_ctrl: lvds-mux-ctrl-hog { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; + line-name = "LVDS_MUX_CTRL"; + output-low; + }; + + usb_mux_ctrl: usb-mux-ctrl-hog { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + line-name = "USB_MUX_CTRL"; + output-high; + }; + }; + + power-monitor@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + + temperature-sensor@4f { + compatible = "ti,tmp1075"; + reg = <0x4f>; + }; + + tcpc@52 { + compatible = "nxp,ptn5110", "tcpci"; + reg = <0x52>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a0>; + interrupt-parent = <&gpio5>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB_A"; + op-sink-microwatt = <0>; + power-role = "dual"; + try-power-role = "sink"; + self-powered; + sink-pdos = ; + source-pdos = ; + + port { + usb_c_a_conn_hs: endpoint { + remote-endpoint = <&usb_a_hs>; + }; + }; + }; + }; + + carrier_eeprom: eeprom@57 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* OSM I2C_B */ +&lpi2c5 { + status = "okay"; + + i2c-mux@70 { + compatible = "nxp,pca9548"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c_mux_carrier_cam_a: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c_mux_carrier_lvds: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + /* I2C on DSI connector pin #4 and #6 */ + i2c_mux_carrier_dsi_1: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + /* I2C on DSI connector pin #52 and #54 */ + i2c_mux_carrier_dsi_2: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c_mux_carrier_cam_b: i2c@4 { + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c_mux_carrier_sfp: i2c@5 { + reg = <5>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +/* OSM SPI_A */ +&lpspi4 { + status = "okay"; +}; + +/* OSM UART_CON, used as the Linux Console */ +&lpuart1 { + status = "okay"; +}; + +/* OSM UART_D */ +&lpuart2 { + status = "okay"; +}; + +/* OSM UART_C */ +&lpuart3 { + status = "okay"; +}; + +/* OSM UART_B */ +&lpuart5 { + status = "okay"; +}; + +/* OSM UART_A */ +&lpuart6 { + status = "okay"; +}; + +&netc_blk_ctrl { + status = "okay"; +}; + +/* OSM MDIO, shared between all ethernet ports */ +&netc_emdio { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mdio>; + + status = "okay"; + + ethphy_a: ethernet-phy@2 { + reg = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a7>; + interrupt-parent = <&gpio1>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + }; + + ethphy_b: ethernet-phy@3 { + reg = <3>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + }; +}; + +&netc_timer { + status = "okay"; +}; + +&netcmix_blk_ctrl { + status = "okay"; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie1 { + status = "okay"; +}; + +/* OSM I2S_A */ +&sai3 { + status = "okay"; +}; + +/* OSM PWM_0 */ +&tpm3 { + status = "okay"; +}; + +/* OSM PWM_1 */ +&tpm4 { + status = "okay"; +}; + +/* OSM PWM_2 */ +&tpm5 { + status = "okay"; +}; + +/* OSM PWM_3 */ +&tpm6 { + status = "okay"; +}; + +/* OSM USB_A */ +&usb2 { + status = "okay"; + + port { + usb_a_hs: endpoint { + remote-endpoint = <&usb_c_a_conn_hs>; + }; + }; +}; + +/* OSM USB_C */ +&usb3 { + status = "okay"; +}; + +&usb3_phy { + status = "okay"; +}; + +/* OSM SDIO_A */ +&usdhc2 { + status = "okay"; +}; + +/* OSM SDIO_B */ +&usdhc3 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx95-toradex-osm.dtsi b/arch/arm64/boot/dts/freescale/imx95-toradex-osm.dtsi new file mode 100644 index 000000000000..8eb7ea4ed9ee --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx95-toradex-osm.dtsi @@ -0,0 +1,1032 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX95 SoM + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx95 + */ + +#include "imx95.dtsi" + +/ { + aliases { + can0 = &flexcan2; + can1 = &flexcan3; + eeprom0 = &som_eeprom; + ethernet0 = &enetc_port0; + ethernet1 = &enetc_port1; + ethernet2 = &enetc_port2; + i2c0 = &lpi2c3; + i2c1 = &lpi2c1; + i2c2 = &lpi2c5; + mmc0 = &usdhc1; + mmc1 = &usdhc2; + mmc2 = &usdhc3; + rtc0 = &rtc_i2c; + rtc1 = &scmi_bbm; + serial0 = &lpuart1; + serial1 = &lpuart6; + serial2 = &lpuart5; + serial3 = &lpuart3; + serial4 = &lpuart2; + usb0 = &usb2; + usb1 = &usb3; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clk_serdes_eth_ref: clock-eth-ref { + compatible = "gpio-gate-clock"; + #clock-cells = <0>; + /* CTRL_ETH_REF_CLK_STBY# */ + enable-gpios = <&som_gpio_expander_0 13 GPIO_ACTIVE_HIGH>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "On-module +V1.8"; + }; + + reg_usb_a_vbus: regulator-usb-a-vbus { + compatible = "regulator-fixed"; + /* OSM USB_A_EN (OSM_AC16) */ + gpios = <&som_gpio_expander_0 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-name = "USB_A_EN"; + }; + + reg_usb_c_vbus: regulator-usb-c-vbus { + compatible = "regulator-fixed"; + /* OSM USB_C_EN (OSM_C10) */ + gpios = <&som_gpio_expander_0 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-name = "USB_C_EN"; + }; + + reg_sdio_a_vmmc: regulator-usdhc2-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdio_a_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 = "SDIO_A_PWR_EN"; + startup-delay-us = <20000>; + }; + + reg_sdio_a_vqmmc: regulator-usdhc2-vqmmc { + compatible = "regulator-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdio_a_vsel>; + gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "PMIC_SDIO_A_VSEL"; + states = <1800000 0x1>, <3300000 0x0>; + }; + + remoteproc-cm7 { + compatible = "fsl,imx95-cm7"; + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu7 0 1 &mu7 1 1 &mu7 3 1>; + memory-region = <&vdev0buffer>, <&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"; + alloc-ranges = <0 0x80000000 0 0x7f000000>; + linux,cma-default; + reusable; + size = <0 0x3c000000>; + }; + + m7_reserved: memory@80000000 { + reg = <0 0x80000000 0 0x1000000>; + 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; + }; + + vdev0buffer: vdev0buffer@88020000 { + compatible = "shared-dma-pool"; + reg = <0 0x88020000 0 0x100000>; + no-map; + }; + + rsc_table: rsc-table@88220000 { + reg = <0 0x88220000 0 0x1000>; + no-map; + }; + }; +}; + +/* OSM ADC_0, ADC_1 */ +&adc1 { + vref-supply = <®_1p8v>; +}; + +/* OSM ETH_A */ +&enetc_port0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth_a>; +}; + +/* OSM ETH_B */ +&enetc_port1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth_b>; +}; + +/* OSM ETH_C */ +&enetc_port2 { + clocks = <&clk_serdes_eth_ref>; + clock-names = "ref"; +}; + +/* OSM CAN_A */ +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can_a>; +}; + +/* OSM CAN_B */ +&flexcan3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can_b>; +}; + +&gpio1 { + gpio-line-names = + "OSM_AA15", /* 0 */ + "OSM_AA16", + "", + "", + "", + "", + "", + "", + "OSM_F19", + "OSM_AA23", + "OSM_G19", /* 10 */ + "OSM_L17"; /* OSM GPIO_A_7/SPI_B_CS1# */ + + status = "okay"; +}; + +&gpio2 { + gpio-line-names = + "", /* 0 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 20 */ + "", + "OSM_AA21", + "OSM_AA20", + "", + "", + "", + "", + "I2C_SOM_SDA", + "I2C_SOM_SCL"; +}; + +&gpio3 { + gpio-line-names = + "OSM_J21", /* 0 */ + "", + "", + "", + "", + "", + "", + "OSM_D21", + "", + "", + "", /* 10 */ + "", + "", + "", + "", + "", + "", + "", + "", + "PMIC_SDIO_A_VSEL"; +}; + +&gpio4 { + gpio-line-names = + "", /* 0 */ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "", + "", + "CTRL_GPIO_EXP_INT#", + "OSM_T2"; +}; + +&gpio5 { + gpio-line-names = + "OSM_D17", /* OSM GPIO_A_0 */ + "OSM_E17", /* OSM GPIO_A_1 */ + "OSM_F17", /* OSM GPIO_A_2 */ + "OSM_G17", /* OSM GPIO_A_3 */ + "", + "", + "", + "", + "OSM_E19", + "OSM_H17", /* OSM GPIO_A_4 */ + "OSM_J17", /* OSM GPIO_A_5 */ + "OSM_D19", + "", + "OSM_K17", /* OSM GPIO_A_6/SPI_A_CS1# */ + "OSM_Y15"; +}; + +/* OSM I2C_A */ +&lpi2c1 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c_a>; + pinctrl-1 = <&pinctrl_i2c_a_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio1 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; +}; + +/* I2C_SOM */ +&lpi2c3 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c_som>, <&pinctrl_ctrl_gpio_exp_int>; + pinctrl-1 = <&pinctrl_i2c_som_gpio>, <&pinctrl_ctrl_gpio_exp_int>; + 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,pcal6416"; + reg = <0x20>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio4>; + interrupts = <14 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "OSM_AC16", /* 0 */ + "OSM_AC15", + "OSM_C10", + "OSM_C8", + "OSM_H19", /* OSM GPIO_B_4 */ + "OSM_J19", /* OSM GPIO_B_5 */ + "OSM_K19", /* OSM GPIO_B_6 */ + "OSM_L19", /* OSM GPIO_B_7 */ + "OSM_V2", + "OSM_L33", + "OSM_AN23", /* 10 */ + "OSM_AN14", + "USB_RECOVERY_CTRL#", + "CTRL_ETH_REF_CLK_STBY#", + "CTRL_DSI_EN/CSI_EN#", + "SPI_B_TPM_CS#"; + + /* + * Switch USB to default position: + * - SoC USB2 -> OSM USB_A + * - SoC USB1 -> OSM USB_C + * Reset configuration: + * - SoC USB1 -> OSM USB_A (USB recovery) + * - SoC USB2 not connected + */ + usb_recov_ctrl: usb-recov-ctrl-hog { + gpio-hog; + gpios = <12 GPIO_ACTIVE_HIGH>; + line-name = "USB_RECOVERY_CTRL#"; + output-high; + }; + }; + + som_gpio_expander_1: gpio@21 { + compatible = "nxp,pcal6416"; + reg = <0x21>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio4>; + interrupts = <14 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "OSM_D3", /* OSM GPIO_C_0 */ + "OSM_D4", /* OSM GPIO_C_1 */ + "OSM_E3", /* OSM GPIO_C_2/CAM_B_PWR */ + "OSM_E4", /* OSM GPIO_C_3/CAM_B_RST# */ + "OSM_F3", /* OSM GPIO_C_4/DISP_VDD_EN */ + "OSM_F4", /* OSM GPIO_C_5/DISP_BL_EN */ + "OSM_G3", /* OSM GPIO_C_6/CAM_A_PWR */ + "OSM_G4", /* OSM GPIO_C_7/CAM_A_RST# */ + "OSM_U32", + "OSM_U33", + "OSM_V32", /* 10 */ + "OSM_V33", + "OSM_W32", + "OSM_W33", + "OSM_Y32", + "OSM_Y33"; + }; + + 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>; + }; +}; + +/* OSM I2C_B */ +&lpi2c5 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c_b>; + pinctrl-1 = <&pinctrl_i2c_b_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio2 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; +}; + +/* OSM SPI_B */ +&lpspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi_b>, <&pinctrl_spi_b_cs0_gpio>; + cs-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>, + <&som_gpio_expander_0 15 GPIO_ACTIVE_LOW>; + + status = "okay"; + + som_tpm: tpm@1 { + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + reg = <0x1>; + /* + * Maximum TPM-supported speed is 18.5 MHz, limited to 12 MHz + * here as lpspi1's per-clock (twice the max speed) is 24 MHz + */ + spi-max-frequency = <12000000>; + }; +}; + +/* OSM SPI_A */ +&lpspi4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi_a>, <&pinctrl_spi_a_cs0_gpio>; + cs-gpios = <&gpio5 14 GPIO_ACTIVE_LOW>; +}; + +/* OSM UART_CON, used as the Linux Console */ +&lpuart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_con>; +}; + +/* OSM UART_D */ +&lpuart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_d>; +}; + +/* OSM UART_C */ +&lpuart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_c>; +}; + +/* OSM UART_B */ +&lpuart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_b>; + uart-has-rtscts; +}; + +/* OSM UART_A */ +&lpuart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_a>; + uart-has-rtscts; +}; + +&mu7 { + status = "okay"; +}; + +/* OSM PCIE_A */ +&pcie0 { + /* PCIE_A_PERST# (OSM V2) */ + reset-gpios = <&som_gpio_expander_0 8 GPIO_ACTIVE_LOW>; +}; + +/* OSM PCIE_B */ +&pcie1 { + /* PCIE_B_PERST# (OSM L33) */ + reset-gpios = <&som_gpio_expander_0 9 GPIO_ACTIVE_LOW>; +}; + +/* OSM I2S_A */ +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s_a>, <&pinctrl_i2s_mclk>; + 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_SAI3>; + 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; +}; + +/* OSM I2S_B */ +&sai5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s_b>; + 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_SAI5>; + 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 = ; +}; + +&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"; + }; + }; + }; +}; + +/* OSM PWM_0 */ +&tpm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0>; +}; + +/* OSM PWM_1 */ +&tpm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; +}; + +/* OSM PWM_2 */ +&tpm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; +}; + +/* OSM PWM_3 */ +&tpm6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; +}; + +/* OSM USB_A */ +&usb2 { + adp-disable; + disable-over-current; + dr_mode = "otg"; + hnp-disable; + srp-disable; + usb-role-switch; + vbus-supply = <®_usb_a_vbus>; +}; + +/* OSM USB_C */ +&usb3 { + fsl,disable-port-power-control; +}; + +&usb3_dwc3 { + dr_mode = "host"; +}; + +&usb3_phy { + vbus-supply = <®_usb_c_vbus>; +}; + +/* On-module eMMC */ +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_emmc>; + pinctrl-1 = <&pinctrl_emmc>; + pinctrl-2 = <&pinctrl_emmc_200mhz>; + no-sd; + no-sdio; + non-removable; + + status = "okay"; +}; + +/* OSM SDIO_A */ +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; + pinctrl-0 = <&pinctrl_sdio_a>, <&pinctrl_sdio_a_cd>; + pinctrl-1 = <&pinctrl_sdio_a>, <&pinctrl_sdio_a_cd>; + pinctrl-2 = <&pinctrl_sdio_a_200mhz>, <&pinctrl_sdio_a_cd>; + pinctrl-3 = <&pinctrl_sdio_a_sleep>, <&pinctrl_sdio_a_cd>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + disable-wp; + vmmc-supply = <®_sdio_a_vmmc>; + vqmmc-supply = <®_sdio_a_vqmmc>; +}; + +/* OSM SDIO_B */ +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_sdio_b>; + pinctrl-1 = <&pinctrl_sdio_b>; + pinctrl-2 = <&pinctrl_sdio_b_200mhz>; + disable-wp; +}; + +&wdog3 { + fsl,ext-reset-output; + + status = "okay"; +}; + +&scmi_iomuxc { + /* OSM MDIO, shared between all ethernet ports */ + pinctrl_mdio: emdiogrp { + fsl,pins = , /* OSM T16 */ + ; /* OSM T15 */ + }; + + /* OSM ETH_A */ + pinctrl_eth_a: enetc0grp { + fsl,pins = , /* OSM K16 */ + , /* OSM J15 */ + , /* OSM H15 */ + , /* OSM G15 */ + , /* OSM H16 */ + , /* OSM G16 */ + , /* OSM M15 */ + , /* OSM R15 */ + , /* OSM K15 */ + , /* OSM L15 */ + , /* OSM N15 */ + ; /* OSM P15 */ + }; + + /* OSM ETH_B */ + pinctrl_eth_b: enetc1grp { + fsl,pins = , /* OSM J2 */ + , /* OSM H1 */ + , /* OSM G1 */ + , /* OSM F1 */ + , /* OSM G2 */ + , /* OSM F2 */ + , /* OSM L1 */ + , /* OSM P1 */ + , /* OSM J1 */ + , /* OSM K1 */ + , /* OSM M1 */ + ; /* OSM N1 */ + }; + + /* OSM CAN_A */ + pinctrl_can_a: flexcan2grp { + fsl,pins = , /* OSM AC17 */ + ; /* OSM AB17 */ + }; + + /* OSM CAN_B */ + pinctrl_can_b: flexcan3grp { + fsl,pins = , /* OSM AC19 */ + ; /* OSM AB19 */ + }; + + /* OSM GPIO_B_2 */ + pinctrl_gpio_b2: gpio1io8grp { + fsl,pins = ; /* OSM F19 */ + }; + + /* OSM SPI_B_CS0# */ + pinctrl_spi_b_cs0_gpio: gpio1io9grp { + fsl,pins = ; /* OSM AA23 */ + }; + + /* OSM GPIO_B_3 */ + pinctrl_gpio_b3: gpio1io10grp { + fsl,pins = ; /* OSM G19 */ + }; + + /* OSM GPIO_A_7/SPI_B_CS1# */ + pinctrl_gpio_a7: gpio1io11grp { + fsl,pins = ; /* OSM L17 */ + }; + + /* OSM PWM_0 as GPIO */ + pinctrl_pwm0_gpio: gpio2io12grp { + fsl,pins = ; /* OSM E18 */ + }; + + /* OSM GPIO_A_0 */ + pinctrl_gpio_a0: gpio5io0grp { + fsl,pins = ; /* OSM D17 */ + }; + + /* OSM GPIO_A_1 */ + pinctrl_gpio_a1: gpio5io1grp { + fsl,pins = ; /* OSM E17 */ + }; + + /* OSM GPIO_A_2 */ + pinctrl_gpio_a2: gpio5io2grp { + fsl,pins = ; /* OSM F17 */ + }; + + /* OSM GPIO_A_3 */ + pinctrl_gpio_a3: gpio5io3grp { + fsl,pins = ; /* OSM G17 */ + }; + + /* OSM GPIO_B_1 */ + pinctrl_gpio_b1: gpio5io8grp { + fsl,pins = ; /* OSM E19 */ + }; + + /* OSM GPIO_A_4 */ + pinctrl_gpio_a4: gpio5io9grp { + fsl,pins = ; /* OSM H17 */ + }; + + /* OSM GPIO_A_5 */ + pinctrl_gpio_a5: gpio5io10grp { + fsl,pins = ; /* OSM J17 */ + }; + + /* OSM GPIO_B_0 */ + pinctrl_gpio_b0: gpio5io11grp { + fsl,pins = ; /* OSM D19 */ + }; + + /* OSM GPIO_A_6/SPI_A_CS1# */ + pinctrl_gpio_a6: gpio5io13grp { + fsl,pins = ; /* OSM K17 */ + }; + + /* OSM SPI_A_CS0# */ + pinctrl_spi_a_cs0_gpio: gpio5io14grp { + fsl,pins = ; /* OSM Y15 */ + }; + + pinctrl_ctrl_gpio_exp_int: gpioexpintgrp { + fsl,pins = ; /* CTRL_GPIO_EXP_INT# */ + }; + + /* OSM I2C_A as GPIOs */ + pinctrl_i2c_a_gpio: lpi2c1gpiogrp { + fsl,pins = , /* OSM AA16 */ + ; /* OSM AA15 */ + }; + + /* OSM I2C_A */ + pinctrl_i2c_a: lpi2c1grp { + fsl,pins = , /* OSM AA16 */ + ; /* OSM AA15 */ + }; + + /* I2C_SOM (On-module I2C) as GPIOs */ + pinctrl_i2c_som_gpio: lpi2c3gpiogrp { + fsl,pins = , /* I2C_SOM_SDA */ + ; /* I2C_SOM_SCL */ + }; + + /* I2C_SOM (On-module I2C) */ + pinctrl_i2c_som: lpi2c3grp { + fsl,pins = , /* I2C_SOM_SDA */ + ; /* I2C_SOM_SCL */ + }; + + /* OSM I2C_B as GPIOs */ + pinctrl_i2c_b_gpio: lpi2c5gpiogrp { + fsl,pins = , /* OSM AA21 */ + ; /* OSM AA20 */ + }; + + /* OSM I2C_B */ + pinctrl_i2c_b: lpi2c5grp { + fsl,pins = , /* OSM AA21 */ + ; /* OSM AA20 */ + }; + + /* OSM SPI_B */ + pinctrl_spi_b: lpspi1grp { + fsl,pins = , /* OSM Y21 */ + , /* OSM Y23 */ + ; /* OSM Y22 */ + }; + + /* OSM SPI_A */ + pinctrl_spi_a: lpspi4grp { + fsl,pins = , /* OSM U16 */ + , /* OSM V15 */ + ; /* OSM U15 */ + }; + + /* OSM UART_CON */ + pinctrl_uart_con: lpuart1grp { + fsl,pins = , /* OSM D23 */ + ; /* OSM D22 */ + }; + + /* OSM UART_D */ + pinctrl_uart_d: lpuart2grp { + fsl,pins = , /* OSM C23 */ + ; /* OSM C22 */ + }; + + /* OSM UART_C */ + pinctrl_uart_c: lpuart3grp { + fsl,pins = , /* OSM B23 */ + ; /* OSM A22 */ + }; + + /* OSM UART_B */ + pinctrl_uart_b: lpuart5grp { + fsl,pins = , /* OSM D13 */ + , /* OSM D14 */ + , /* OSM D16 */ + ; /* OSM D15 */ + }; + + /* OSM UART_A */ + pinctrl_uart_a: lpuart6grp { + fsl,pins = , /* OSM B13 */ + , /* OSM A14 */ + , /* OSM C14 */ + ; /* OSM C13 */ + }; + + /* OSM PCIE_WAKE# */ + pinctrl_pcie_wake: pciewakegrp { + fsl,pins = ; /* OSM T2 */ + }; + + /* OSM I2S_A */ + pinctrl_i2s_a: sai3grp { + fsl,pins = , /* OSM W20 */ + , /* OSM V21 */ + , /* OSM W21 */ + ; /* OSM W18 */ + }; + + /* OSM I2S_MCLK */ + pinctrl_i2s_mclk: sai3mclkgrp { + fsl,pins = ; /* OSM V18 */ + }; + + /* OSM I2S_B */ + pinctrl_i2s_b: sai5grp { + fsl,pins = , /* OSM T19 */ + , /* OSM V19 */ + , /* OSM W19 */ + ; /* OSM T18 */ + }; + + /* OSM PWM_0 */ + pinctrl_pwm0: tpm3ch2grp { + fsl,pins = ; /* OSM E18 */ + }; + + /* OSM PWM_1 */ + pinctrl_pwm1: tpm4ch2grp { + fsl,pins = ; /* OSM F18 */ + }; + + /* OSM PWM_2 */ + pinctrl_pwm2: tpm5ch2grp { + fsl,pins = ; /* OSM G18 */ + }; + + /* OSM PWM_3 */ + pinctrl_pwm3: tpm6ch2grp { + fsl,pins = ; /* OSM H18 */ + }; + + /* On-module eMMC (max 200MHz) */ + pinctrl_emmc_200mhz: usdhc1-200mhzgrp { + fsl,pins = , /* eMMC_CLK */ + , /* eMMC_CMD */ + , /* eMMC_DATA0 */ + , /* eMMC_DATA1 */ + , /* eMMC_DATA2 */ + , /* eMMC_DATA3 */ + , /* eMMC_DATA4 */ + , /* eMMC_DATA5 */ + , /* eMMC_DATA6 */ + , /* eMMC_DATA7 */ + ; /* eMMC_STROBE */ + }; + + /* On-module eMMC (max 100MHz) */ + pinctrl_emmc: usdhc1grp { + fsl,pins = , /* eMMC_CLK */ + , /* eMMC_CMD */ + , /* eMMC_DATA0 */ + , /* eMMC_DATA1 */ + , /* eMMC_DATA2 */ + , /* eMMC_DATA3 */ + , /* eMMC_DATA4 */ + , /* eMMC_DATA5 */ + , /* eMMC_DATA6 */ + , /* eMMC_DATA7 */ + ; /* eMMC_STROBE */ + }; + + /* OSM SDIO_A (max 200MHz) */ + pinctrl_sdio_a_200mhz: usdhc2-200mhzgrp { + fsl,pins = , /* OSM F21 */ + , /* OSM E20 */ + , /* OSM G20 */ + , /* OSM G21 */ + , /* OSM H20 */ + ; /* OSM H21 */ + }; + + /* OSM SDIO_A_CD# */ + pinctrl_sdio_a_cd: usdhc2-cdgrp { + fsl,pins = ; /* OSM J21 */ + }; + + /* OSM SDIO_A_PWR_EN */ + pinctrl_sdio_a_pwr_en: usdhc2-pwrengrp { + fsl,pins = ; /* OSM D21 */ + }; + + /* OSM SDIO_A (sleep mode) */ + pinctrl_sdio_a_sleep: usdhc2-sleepgrp { + fsl,pins = , /* OSM F21 */ + , /* OSM E20 */ + , /* OSM G20 */ + , /* OSM G21 */ + , /* OSM H20 */ + ; /* OSM H21 */ + }; + + /* PMIC_SDIO_A_VSEL */ + pinctrl_sdio_a_vsel: usdhc2-vselgrp { + fsl,pins = ; /* PMIC_SDIO_A_VSEL */ + }; + + /* OSM SDIO_A (max 100MHz) */ + pinctrl_sdio_a: usdhc2grp { + fsl,pins = , /* OSM F21 */ + , /* OSM E20 */ + , /* OSM G20 */ + , /* OSM G21 */ + , /* OSM H20 */ + ; /* OSM H21 */ + }; + + /* OSM SDIO_B (max 200MHz) */ + pinctrl_sdio_b_200mhz: usdhc3-200mhzgrp { + fsl,pins = , /* OSM K20 */ + , /* OSM K21 */ + , /* OSM L20 */ + , /* OSM L21 */ + , /* OSM M21 */ + ; /* OSM N20 */ + }; + + /* OSM SDIO_B (max 100MHz) */ + pinctrl_sdio_b: usdhc3grp { + fsl,pins = , /* OSM K20 */ + , /* OSM K21 */ + , /* OSM L20 */ + , /* OSM L21 */ + , /* OSM M21 */ + ; /* OSM N20 */ + }; +}; -- cgit v1.2.3 From 92108b234bfa39f97335f7f635ac49d5ecea5e82 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:09:58 +0530 Subject: Documentation/firmware: add imx/se to other_interfaces Documents i.MX SoC's Service layer and C_DEV driver for selected SoC(s) that contains the NXP hardware IP(s) for Secure Enclaves(se) like: - NXP EdgeLock Enclave on i.MX93 & i.MX8ULP Signed-off-by: Pankaj Gupta Signed-off-by: Frank Li --- .../driver-api/firmware/other_interfaces.rst | 238 +++++++++++++++++++++ 1 file changed, 238 insertions(+) diff --git a/Documentation/driver-api/firmware/other_interfaces.rst b/Documentation/driver-api/firmware/other_interfaces.rst index 06ac89adaafb..984ee3ecc8dc 100644 --- a/Documentation/driver-api/firmware/other_interfaces.rst +++ b/Documentation/driver-api/firmware/other_interfaces.rst @@ -49,3 +49,241 @@ of the requests on to a secure monitor (EL3). .. kernel-doc:: drivers/firmware/stratix10-svc.c :export: + +NXP Secure Enclave Firmware Interface +-------------------------------------- + +Introduction +~~~~~~~~~~~~ +NXP i.MX hardware IPs such as EdgeLock Enclave (ELE) and V2X create an +embedded secure enclave within the SoC boundary to enable features like: + +- Hardware Security Module (HSM) +- Security Hardware Extension (SHE) +- Vehicular to Anything (V2X) + +Each of the above features is enabled through a dedicated NXP hardware IP +on the SoC. A single SoC may contain more than one such hardware IP, that +is, more than one secure enclave can coexist. + +NXP SoCs with such secure enclave (SE) IPs are: +i.MX93, i.MX8ULP + +To communicate with one or more coexisting SEs on the SoC, there are +dedicated messaging units (MU) per SE. Each coexisting SE can have one or +more exclusive MUs dedicated to itself. No MU is shared between two SEs. +MU communication is realized using the mailbox driver. Each secure enclave +can serve multiple clients by virtue of these exclusive MUs, and can +distinguish transactions from different clients based on the MU used and +the core security state. The communication between clients and secure +enclaves uses a command/response mechanism. Each client can expose a +specific set of secure enclave features to higher layers, based on the +commands it supports. For example, a secure enclave can simultaneously +serve an OP-TEE TA and a Linux middleware client. Each client exposes a +specific set of secure enclave features based on its supported command set. + +NXP Secure Enclave (SE) Interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +MUs are not shared between SEs. For an SoC like i.MX95, which has multiple +SEs such as HSM, V2X-HSM, and V2X-SHE, all SEs and their ``se-if`` +interfaces dedicated to a particular SE are enumerated and provisioned +using the single compatible node ``fsl,imx95-se``. + +Each ``se-if`` comprises two layers: + +- (C_DEV Layer) User-space software-access interface. +- (Service Layer) OS-level software-access interface. + +:: + + +--------------------------------------------+ + | Character Device(C_DEV) | + | | + | +---------+ +---------+ +---------+ | + | | misc #1 | | misc #2 | ... | misc #n | | + | | dev | | dev | | dev | | + | +---------+ +---------+ +---------+ | + | +-------------------------+ | + | | Misc. Dev Sync Logic | | + | +-------------------------+ | + | | + +--------------------------------------------+ + +:: + + +--------------------------------------------+ + | Service Layer | + | | + | +-----------------------------+ | + | | Message Serialization Logic | | + | +-----------------------------+ | + | +---------------+ | + | | imx-mailbox | | + | | mailbox.c | | + | +---------------+ | + | | + +--------------------------------------------+ + +- service layer: + This layer ensures the communication protocol defined for interaction + with firmware. + + The firmware communication protocol provides two guarantees: + + - Serializing the messages to be sent over an MU. + - Firmware can handle one command message at a time. + +- c_dev: + This layer offers character device contexts, created as + ``/dev/_mux_chx``. Using multiple device contexts multiplexed over + a single MU, userspace applications can use file operations (fops) such + as ``write`` and ``read`` to send a command message and read back the + response to/from firmware. These fops use the service layer API to + communicate with firmware. + + Misc-device (``/dev/_mux_chn``) synchronization protocol:: + + Non-Secure + Secure + | + | + +-----------+ +-------------+ | + | se_ctrl.c +<---->+imx-mailbox.c| | + | | | mailbox.c +<-->+------+ +------+ + +-----+-----+ +-------------+ | MU X +<-->+ ELE | + | +------+ +------+ + +----------------+ | + | | | + v v | + logical logical | + receiver waiter | + + + | + | | | + | | | + | +----+------+ | + | | | | + | | | | + device_ctx device_ctx device_ctx | + | + User 0 User 1 User Y | + +------+ +------+ +------+ | + |misc.c| |misc.c| |misc.c| | + kernel space +------+ +------+ +------+ | + | + +---------------------------------------------------- | + | | | | + userspace /dev/ele_muXch0 | | | + /dev/ele_muXch1 | | + /dev/ele_muXchY | + | + +When a user sends a command to the firmware, it registers its +``device_ctx`` as a waiter of a response from firmware. + +The secure enclave firmware manages storage over a Linux filesystem. +For this, ``c_dev`` provisions a dedicated device context called the +command-receiver. + + +ELE_STORAGE_OPEN_REQ concurrency and command-receiver exclusivity +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A userspace-created ``dev_ctx`` becomes the storage subordinate to FW by +being registered as the command-receiver via +``set_dev_ctx_as_command_receiver()``. FW sends NVM callback commands to +this ``dev_ctx`` via that priv's MU, on which the ``dev_ctx`` was created. +Once a userspace ``dev_ctx`` on one priv is registered as the +command-receiver, after opening the storage handle with FW, FW enforces a +global one-storage-instance limit: a concurrent ELE_STORAGE_OPEN_REQ +arriving over this or any other priv's MU is rejected by FW itself, before +any storage handle is allocated. The driver uses three layers of +protection; the sequence below shows how a concurrent race is handled +safely:: + + Userspace A Kernel (se_ctrl) FW (ELE) Userspace B + | | | | + |--ioctl(SEND_RCV)-->| | | + | [advisory check under | | + | modify_lock: no receiver] | | + | [acquire se_if_cmd_lock] |--ioctl(SEND_RCV)-> + | | | [advisory check | + | | | passes: TOCTOU] | + | | | [blocks on | + | | | se_if_cmd_lock] | + | ele_msg_send_rcv() | | + | |--STORAGE_OPEN_REQ--->| | + | |<--STORAGE_OPEN_RSP---| | + | fw_api_specific_ops(): | | + | set_dev_ctx_as_command_receiver| | + | [re-check under modify_lock] | | + | [release se_if_cmd_lock] | | + |<--ioctl 0----------| | | + | | | [B gets lock] | + | | |--STORAGE_OPEN_REQ-> + | | | [FW rejects: | + | | | one storage | + | | | at a time] | + | | |<--ERROR_RSP------| + | | se_val_rsp_hdr_n_status: -EPERM | + | | fw_api_specific_ops not called | + | |<--ioctl -EPERM-to B------------------->| + +The three protection layers are: + +1. Advisory early check (under modify_lock, before send): fast-path + rejection if a receiver is already registered. Not the final gate + because modify_lock is released before the MU send (TOCTOU window). + +2. ``se_if_cmd_lock``: held for the entire send+receive cycle, so only + one ioctl command is in flight on a given MU at a time. + +3. ``set_dev_ctx_as_command_receiver()`` re-checks under modify_lock + after the response arrives. If two callers race past layer 1, FW + itself rejects the second ELE_STORAGE_OPEN_REQ before any handle is + allocated. + +Signal handling after a completed hardware operation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A signal may arrive after the firmware has already executed the command +and delivered its response into the MU receive buffer. The driver detects +this case and preserves state before returning ``-EINTR``:: + + Userspace Kernel (se_ctrl) FW (ELE) + | | | + |--ioctl(SEND_RCV)-->| | + | ele_msg_send_rcv() | + | |--CMD_REQ------------>| + | [signal arrives] | | (FW executes, + | | | allocates handle, + | | | writes response) + | |<--CMD_RSP------------| + | wait_for_completion_interruptible() | + | wakes: signal seen -> -ERESTARTSYS | + | | | + | [response is in rx_msg: | + | validate with | + | se_val_rsp_hdr_n_status()] | + | [fw_api_specific_ops() | + | (is_cmd_interrupted=true): | + | for SESSION_OPEN: record | + | handle, close session via | + | se_close_session(), clear; | + | for STORAGE_OPEN: record | + | handle, close storage via | + | se_close_storage(), return 0] | + | err = -EINTR | + | (not -ERESTARTSYS: | + | prevents VFS auto-restart) | + |<--ioctl -EINTR-----| | + | | | + | [signal handler runs; userspace decides | + | whether to re-issue; FW handle tracked | + | or cleaned up; no firmware resource leak]| + +Returning ``-EINTR`` instead of ``-ERESTARTSYS`` is intentional: the VFS +would transparently restart an ioctl on ``-ERESTARTSYS``, re-running the +command with already-zeroed shared input buffers. ``-EINTR`` lets userspace +enter its signal handler and decide whether to reissue the command. + +.. kernel-doc:: drivers/firmware/imx/se_ctrl.c + :export: -- cgit v1.2.3 From 1af212aacb3f6a33106cfd86a50acda47c65b034 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:09:59 +0530 Subject: dt-bindings: arm: fsl: add imx-se-fw binding doc The NXP security hardware IP(s) like: i.MX EdgeLock Enclave, V2X etc., creates an embedded secure enclave within the SoC boundary to enable features like: - HSM - SHE - V2X Secure-Enclave(s) communication interface are typically via message unit, i.e., based on mailbox linux kernel driver. This driver enables communication ensuring well defined message sequence protocol between Application Core and enclave's firmware. Driver configures multiple misc-device on the MU, for multiple user-space applications, to be able to communicate over single MU. It exists on some i.MX processors. e.g. i.MX8ULP, i.MX93 etc. Signed-off-by: Pankaj Gupta Reviewed-by: Rob Herring (Arm) Tested-by: Peng Fan #i.MX8ULP-EVK Signed-off-by: Frank Li --- .../devicetree/bindings/firmware/fsl,imx-se.yaml | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml diff --git a/Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml b/Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml new file mode 100644 index 000000000000..fa81adbf9b80 --- /dev/null +++ b/Documentation/devicetree/bindings/firmware/fsl,imx-se.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/firmware/fsl,imx-se.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX HW Secure Enclave(s) EdgeLock Enclave + +maintainers: + - Pankaj Gupta + +description: | + NXP's SoC may contain one or multiple embedded secure-enclave HW + IP(s) like i.MX EdgeLock Enclave, V2X etc. These NXP's HW IP(s) + enables features like + - Hardware Security Module (HSM), + - Security Hardware Extension (SHE), and + - Vehicular to Anything (V2X) + + Communication interface to the secure-enclaves(se) is based on the + messaging unit(s). + +properties: + compatible: + enum: + - fsl,imx8ulp-se-ele-hsm + - fsl,imx93-se-ele-hsm + - fsl,imx95-se-ele-hsm + + mboxes: + items: + - description: mailbox phandle to send message to se firmware + - description: mailbox phandle to receive message from se firmware + + mbox-names: + items: + - const: tx + - const: rx + + memory-region: + maxItems: 1 + + sram: + maxItems: 1 + +required: + - compatible + - mboxes + - mbox-names + +allOf: + # memory-region + - if: + properties: + compatible: + contains: + enum: + - fsl,imx8ulp-se-ele-hsm + - fsl,imx93-se-ele-hsm + then: + required: + - memory-region + else: + properties: + memory-region: false + + # sram + - if: + properties: + compatible: + contains: + enum: + - fsl,imx8ulp-se-ele-hsm + then: + required: + - sram + + else: + properties: + sram: false + +additionalProperties: false + +examples: + - | + secure-enclave { + compatible = "fsl,imx95-se-ele-hsm"; + mboxes = <&ele_mu0 0 0>, <&ele_mu0 1 0>; + mbox-names = "tx", "rx"; + }; +... -- cgit v1.2.3 From dfc0183f20c3b21d67a3e4e6dd34b833a83c19fc Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:10:00 +0530 Subject: firmware: imx: add driver for NXP EdgeLock Enclave Add MU-based communication interface for secure enclave. NXP hardware IP(s) for secure-enclaves like Edgelock Enclave(ELE), are embedded in the SoC to support the features like HSM, SHE & V2X, using message based communication interface. The secure enclave FW communicates with Linux over single or multiple dedicated messaging unit(MU) based interface(s). Exists on i.MX SoC(s) like i.MX8ULP, i.MX93, i.MX95 etc. For i.MX9x SoC(s) there is at least one dedicated ELE MU(s) for each world - Linux(one or more) and OPTEE-OS (one or more). Other dependent kernel drivers will be: - NVMEM: that supports non-volatile devices like EFUSES, managed by NXP's secure-enclave. Signed-off-by: Pankaj Gupta Reviewed-by: Frank Li Signed-off-by: Frank Li --- drivers/firmware/imx/Kconfig | 12 + drivers/firmware/imx/Makefile | 2 + drivers/firmware/imx/ele_base_msg.c | 341 +++++++++++++++++++++ drivers/firmware/imx/ele_base_msg.h | 100 ++++++ drivers/firmware/imx/ele_common.c | 589 ++++++++++++++++++++++++++++++++++++ drivers/firmware/imx/ele_common.h | 45 +++ drivers/firmware/imx/se_ctrl.c | 523 ++++++++++++++++++++++++++++++++ drivers/firmware/imx/se_ctrl.h | 112 +++++++ include/linux/firmware/imx/se_api.h | 14 + 9 files changed, 1738 insertions(+) create mode 100644 drivers/firmware/imx/ele_base_msg.c create mode 100644 drivers/firmware/imx/ele_base_msg.h create mode 100644 drivers/firmware/imx/ele_common.c create mode 100644 drivers/firmware/imx/ele_common.h create mode 100644 drivers/firmware/imx/se_ctrl.c create mode 100644 drivers/firmware/imx/se_ctrl.h create mode 100644 include/linux/firmware/imx/se_api.h diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig index 127ad752acf8..93ac339800e2 100644 --- a/drivers/firmware/imx/Kconfig +++ b/drivers/firmware/imx/Kconfig @@ -55,3 +55,15 @@ config IMX_SCMI_MISC_DRV core that could provide misc functions such as board control. This driver can also be built as a module. + +config IMX_SEC_ENCLAVE + tristate "i.MX Embedded Secure Enclave - EdgeLock Enclave Firmware driver." + depends on MAILBOX && ((IMX_MBOX && ARCH_MXC && ARM64) || COMPILE_TEST) + select FW_LOADER + default m if ARCH_MXC + + help + Exposes APIs supported by the iMX Secure Enclave HW IP called: + - EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93), + like base, HSM, V2X & SHE using the SAB protocol via the shared Messaging + Unit. diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile index 3bbaffa6e347..4412b15846b1 100644 --- a/drivers/firmware/imx/Makefile +++ b/drivers/firmware/imx/Makefile @@ -4,3 +4,5 @@ obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o obj-${CONFIG_IMX_SCMI_CPU_DRV} += sm-cpu.o obj-${CONFIG_IMX_SCMI_MISC_DRV} += sm-misc.o obj-${CONFIG_IMX_SCMI_LMM_DRV} += sm-lmm.o +sec_enclave-objs = se_ctrl.o ele_common.o ele_base_msg.o +obj-${CONFIG_IMX_SEC_ENCLAVE} += sec_enclave.o diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c new file mode 100644 index 000000000000..dba6f0ee83ed --- /dev/null +++ b/drivers/firmware/imx/ele_base_msg.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2025 NXP + */ + +#include + +#include +#include +#include +#include + +#include "ele_base_msg.h" +#include "ele_common.h" + +#define FW_DBG_DUMP_FIXED_STR "ELE" + +static void ele_get_info_cleanup(struct se_if_priv *priv, u32 *buf, dma_addr_t d_addr, + size_t size) +{ + if (priv->mem_pool) + gen_pool_free(priv->mem_pool, (unsigned long)buf, size); + else + dma_free_coherent(priv->dev, size, buf, d_addr); +} + +/** + * ele_get_info() - retrieve SoC and firmware information from the ELE. + * @priv: pointer to the SE interface private data. + * @s_info: output buffer; filled with device info on success. + * + * Allocates a DMA-coherent bounce buffer (from the gen_pool if available, + * otherwise from the DMA API), sends an ELE_GET_INFO_REQ command, and copies + * the result into @s_info. + * + * Return: 0 on success, negative errno on failure. + */ +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) +{ + dma_addr_t get_info_addr = 0; + void *get_info_data = NULL; + u32 get_info_len; + int ret; + + if (!priv) + return -EINVAL; + + memset(s_info, 0x0, sizeof(*s_info)); + + struct se_api_msg *tx_msg __free(kfree) = + kzalloc(ELE_GET_INFO_REQ_MSG_SZ, GFP_KERNEL); + if (!tx_msg) + return -ENOMEM; + + struct se_api_msg *rx_msg __free(kfree) = + kzalloc(ELE_GET_INFO_RSP_MSG_SZ, GFP_KERNEL); + if (!rx_msg) + return -ENOMEM; + + get_info_len = ELE_GET_INFO_BUFF_SZ; + if (priv->mem_pool) + get_info_data = gen_pool_dma_alloc(priv->mem_pool, + get_info_len, + &get_info_addr); + else + get_info_data = dma_alloc_coherent(priv->dev, + get_info_len, + &get_info_addr, + GFP_KERNEL); + if (!get_info_data) { + dev_err(priv->dev, + "%s: Failed to allocate get_info_addr.\n", __func__); + return -ENOMEM; + } + + /* gen_pool_dma_alloc() does not zero the buffer. */ + memset(get_info_data, 0, get_info_len); + + se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, + ELE_GET_INFO_REQ, ELE_GET_INFO_REQ_MSG_SZ, true); + + tx_msg->data[0] = upper_32_bits(get_info_addr); + tx_msg->data[1] = lower_32_bits(get_info_addr); + tx_msg->data[2] = sizeof(*s_info); + ret = ele_msg_send_rcv(priv, tx_msg, ELE_GET_INFO_REQ_MSG_SZ, rx_msg, + ELE_GET_INFO_RSP_MSG_SZ); + if (ret < 0) { + ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); + return ret; + } + + ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_GET_INFO_REQ, + ELE_GET_INFO_RSP_MSG_SZ, + priv->if_defs->base_api_ver); + if (ret < 0) { + ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); + return ret; + } + + memcpy(s_info, get_info_data, sizeof(*s_info)); + + ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); + + return ret; +} + +/** + * ele_fetch_soc_info() - wrapper around ele_get_info() for generic callers. + * @priv: pointer to the SE interface private data. + * @data: output buffer of at least sizeof(struct ele_dev_info) bytes. + * + * Return: 0 on success, negative errno on failure. + */ +int ele_fetch_soc_info(struct se_if_priv *priv, void *data) +{ + return ele_get_info(priv, (struct ele_dev_info *)data); +} + +/** + * ele_ping() - send a ping command to the secure enclave. + * @priv: pointer to the SE interface private data. + * + * Verifies that the secure enclave is alive and responsive. + * + * Return: 0 on success, negative errno on failure. + */ +int ele_ping(struct se_if_priv *priv) +{ + int ret; + + if (!priv) + return -EINVAL; + + struct se_api_msg *tx_msg __free(kfree) = kzalloc(ELE_PING_REQ_SZ, + GFP_KERNEL); + if (!tx_msg) + return -ENOMEM; + + struct se_api_msg *rx_msg __free(kfree) = kzalloc(ELE_PING_RSP_SZ, + GFP_KERNEL); + if (!rx_msg) + return -ENOMEM; + + se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, + ELE_PING_REQ, ELE_PING_REQ_SZ, true); + + ret = ele_msg_send_rcv(priv, tx_msg, ELE_PING_REQ_SZ, rx_msg, + ELE_PING_RSP_SZ); + if (ret < 0) + return ret; + + ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_PING_REQ, + ELE_PING_RSP_SZ, + priv->if_defs->base_api_ver); + + return ret; +} + +/** + * ele_service_swap() - issue an ELE service-swap (IMEM export/import) command. + * @priv: pointer to the SE interface private data. + * @addr: DMA address of the IMEM buffer; must fit in 32 bits. + * @addr_size: size of the buffer at @addr in bytes. + * @flag: ELE_IMEM_EXPORT or ELE_IMEM_IMPORT. + * + * Return: exported size in bytes (ELE_IMEM_EXPORT), 0 (ELE_IMEM_IMPORT), + * or negative errno on failure. + */ +int ele_service_swap(struct se_if_priv *priv, + dma_addr_t addr, + u32 addr_size, u16 flag) +{ + int ret; + + if (!priv) + return -EINVAL; + + if (upper_32_bits(addr)) { + dev_err(priv->dev, + "ELE service-swap address exceeds 32-bit range: %pad\n", + &addr); + return -ERANGE; + } + + struct se_api_msg *tx_msg __free(kfree) = + kzalloc(ELE_SERVICE_SWAP_REQ_MSG_SZ, GFP_KERNEL); + if (!tx_msg) + return -ENOMEM; + + struct se_api_msg *rx_msg __free(kfree) = + kzalloc(ELE_SERVICE_SWAP_RSP_MSG_SZ, GFP_KERNEL); + if (!rx_msg) + return -ENOMEM; + + se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, + ELE_SERVICE_SWAP_REQ, ELE_SERVICE_SWAP_REQ_MSG_SZ, true); + + tx_msg->data[0] = flag; + tx_msg->data[1] = addr_size; + tx_msg->data[2] = ELE_NONE_VAL; + tx_msg->data[3] = lower_32_bits(addr); + ret = se_update_msg_chksum((u32 *)&tx_msg[0], ELE_SERVICE_SWAP_REQ_MSG_SZ); + if (ret) + return -EINVAL; + + ret = ele_msg_send_rcv(priv, tx_msg, ELE_SERVICE_SWAP_REQ_MSG_SZ, + rx_msg, ELE_SERVICE_SWAP_RSP_MSG_SZ); + if (ret < 0) + return ret; + + ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_SERVICE_SWAP_REQ, + ELE_SERVICE_SWAP_RSP_MSG_SZ, + priv->if_defs->base_api_ver); + if (ret) + return ret; + + if (flag == ELE_IMEM_EXPORT) + ret = rx_msg->data[1]; + else + ret = 0; + + return ret; +} + +/** + * ele_fw_authenticate() - authenticate a firmware container via the ELE. + * @priv: pointer to the SE interface private data. + * @contnr_addr: DMA address of the firmware container; must fit in 32 bits. + * @img_addr: DMA address of the firmware image; must fit in 32 bits. + * + * Return: 0 on success, negative errno on failure. + */ +int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr, + dma_addr_t img_addr) +{ + int ret; + + if (!priv) + return -EINVAL; + + if (upper_32_bits(contnr_addr) || upper_32_bits(img_addr)) { + dev_err(priv->dev, "Wrong address: %pad %pad\n", &contnr_addr, &img_addr); + return -EINVAL; + } + + struct se_api_msg *tx_msg __free(kfree) = + kzalloc(ELE_FW_AUTH_REQ_SZ, GFP_KERNEL); + if (!tx_msg) + return -ENOMEM; + + struct se_api_msg *rx_msg __free(kfree) = + kzalloc(ELE_FW_AUTH_RSP_MSG_SZ, GFP_KERNEL); + if (!rx_msg) + return -ENOMEM; + + se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, + ELE_FW_AUTH_REQ, ELE_FW_AUTH_REQ_SZ, true); + + tx_msg->data[0] = lower_32_bits(contnr_addr); + tx_msg->data[1] = 0; + tx_msg->data[2] = lower_32_bits(img_addr); + + ret = ele_msg_send_rcv(priv, tx_msg, ELE_FW_AUTH_REQ_SZ, rx_msg, + ELE_FW_AUTH_RSP_MSG_SZ); + if (ret < 0) + return ret; + + ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_FW_AUTH_REQ, + ELE_FW_AUTH_RSP_MSG_SZ, + priv->if_defs->base_api_ver); + + return ret; +} + +/** + * ele_debug_dump() - retrieve and log the ELE debug dump buffer. + * @priv: pointer to the SE interface private data. + * + * Repeatedly issues ELE_DEBUG_DUMP_REQ commands and logs the responses via + * dev_info() until no more data is available or the maximum packet count is + * reached. + * + * Return: 0 on success, negative errno on failure. + */ +int ele_debug_dump(struct se_if_priv *priv) +{ + bool keep_logging; + int msg_ex_cnt; + int ret; + int i; + + if (!priv) + return -EINVAL; + + struct se_api_msg *tx_msg __free(kfree) = kzalloc(ELE_DEBUG_DUMP_REQ_SZ, + GFP_KERNEL); + if (!tx_msg) + return -ENOMEM; + + struct se_api_msg *rx_msg __free(kfree) = kzalloc(ELE_DEBUG_DUMP_RSP_SZ, + GFP_KERNEL); + if (!rx_msg) + return -ENOMEM; + + se_fill_cmd_msg_hdr(priv, &tx_msg->header, ELE_DEBUG_DUMP_REQ, + ELE_DEBUG_DUMP_REQ_SZ, true); + + msg_ex_cnt = 0; + do { + memset(rx_msg, 0x0, ELE_DEBUG_DUMP_RSP_SZ); + + ret = ele_msg_send_rcv(priv, tx_msg, ELE_DEBUG_DUMP_REQ_SZ, + rx_msg, ELE_DEBUG_DUMP_RSP_SZ); + if (ret < 0) + return ret; + + ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_DEBUG_DUMP_REQ, + ELE_DEBUG_DUMP_RSP_SZ, + priv->if_defs->base_api_ver); + if (ret) { + dev_err(priv->dev, "Dump_Debug_Buffer Error: %x.\n", ret); + break; + } + keep_logging = (rx_msg->header.size >= (ELE_DEBUG_DUMP_RSP_SZ >> 2) && + msg_ex_cnt < ELE_MAX_DBG_DMP_PKT); + + rx_msg->header.size -= 2; + + if (rx_msg->header.size > 2) + rx_msg->header.size--; + + for (i = 0; i < rx_msg->header.size; i += 2) + dev_info(priv->dev, "%s%02x_%02x: 0x%08x 0x%08x\n", + FW_DBG_DUMP_FIXED_STR, msg_ex_cnt, i, + rx_msg->data[i + 1], rx_msg->data[i + 2]); + + msg_ex_cnt++; + } while (keep_logging); + + return ret; +} diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h new file mode 100644 index 000000000000..02525d5e2873 --- /dev/null +++ b/drivers/firmware/imx/ele_base_msg.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2025 NXP + * + * Header file for the EdgeLock Enclave Base API(s). + */ + +#ifndef ELE_BASE_MSG_H +#define ELE_BASE_MSG_H + +#include +#include +#include + +#include "se_ctrl.h" + +#define ELE_NONE_VAL 0x0 +#define ELE_MAX_DBG_DMP_PKT 50 + +#define ELE_PING_REQ 0x01 +#define ELE_PING_REQ_SZ 0x04 +#define ELE_PING_RSP_SZ 0x08 + +#define ELE_FW_AUTH_REQ 0x02 +#define ELE_FW_AUTH_REQ_SZ 0x10 +#define ELE_FW_AUTH_RSP_MSG_SZ 0x08 + +#define ELE_DEBUG_DUMP_REQ 0x21 +#define ELE_DEBUG_DUMP_REQ_SZ 0x4 +#define ELE_DEBUG_DUMP_RSP_SZ 0x5c + +#define ELE_GET_INFO_REQ 0xda +#define ELE_GET_INFO_REQ_MSG_SZ 0x10 +#define ELE_GET_INFO_RSP_MSG_SZ 0x08 + +#define MAX_UID_SIZE (16) +#define DEV_GETINFO_ROM_PATCH_SHA_SZ (32) +#define DEV_GETINFO_FW_SHA_SZ (32) +#define DEV_GETINFO_OEM_SRKH_SZ (64) +#define DEV_GETINFO_MIN_VER_MASK 0xff +#define DEV_GETINFO_MAJ_VER_MASK 0xff00 +#define ELE_DEV_INFO_EXTRA_SZ 0x60 + +struct dev_info { + u8 cmd; + u8 ver; + u16 length; + u16 soc_id; + u16 soc_rev; + u16 lmda_val; + u8 ssm_state; + u8 dev_atts_api_ver; + u8 uid[MAX_UID_SIZE]; + u8 sha_rom_patch[DEV_GETINFO_ROM_PATCH_SHA_SZ]; + u8 sha_fw[DEV_GETINFO_FW_SHA_SZ]; +}; + +struct dev_addn_info { + u8 oem_srkh[DEV_GETINFO_OEM_SRKH_SZ]; + u8 trng_state; + u8 csal_state; + u8 imem_state; + u8 reserved2; +}; + +struct ele_dev_info { + struct dev_info d_info; + struct dev_addn_info d_addn_info; +}; + +#define ELE_GET_INFO_BUFF_SZ (sizeof(struct ele_dev_info) \ + + ELE_DEV_INFO_EXTRA_SZ) + +#define ELE_SERVICE_SWAP_REQ 0xdf +#define ELE_SERVICE_SWAP_REQ_MSG_SZ 0x18 +#define ELE_SERVICE_SWAP_RSP_MSG_SZ 0x0c +#define ELE_IMEM_SIZE 0x10000 +#define ELE_IMEM_STATE_OK 0xca +#define ELE_IMEM_STATE_BAD 0xfe +#define ELE_IMEM_STATE_WORD 0x27 +#define ELE_IMEM_STATE_MASK 0x00ff0000 +#define ELE_IMEM_EXPORT 0x1 +#define ELE_IMEM_IMPORT 0x2 + +#define GET_SERIAL_NUM_FROM_UID(x, uid_word_sz) ({\ + const u8 *__x = (const u8 *)(x); \ + size_t __sz = (uid_word_sz); \ + ((u64)get_unaligned_le32(__x + (__sz - 1) * sizeof(u32)) << 32) | \ + get_unaligned_le32(__x); \ + }) + +int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info); +int ele_fetch_soc_info(struct se_if_priv *priv, void *data); +int ele_ping(struct se_if_priv *priv); +int ele_service_swap(struct se_if_priv *priv, dma_addr_t addr, + u32 addr_size, u16 flag); +int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr, + dma_addr_t img_addr); +int ele_debug_dump(struct se_if_priv *priv); +#endif diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c new file mode 100644 index 000000000000..c4f87fd0fe5f --- /dev/null +++ b/drivers/firmware/imx/ele_common.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2025 NXP + */ + +#include "ele_base_msg.h" +#include "ele_common.h" + +/** + * se_update_msg_chksum() - calculate and update message checksum word. + * @msg: message buffer. + * @msg_len: message length in bytes. + * + * The message length must be 4-byte aligned. The last word is treated as the + * checksum field and is not included in the checksum calculation. + * + * Return: 0 on success, negative errno on failure. + */ +int se_update_msg_chksum(u32 *msg, u32 msg_len) +{ + u32 nb_words; + u32 chksum = 0; + u32 i; + + if (!msg) + return -EINVAL; + + if (msg_len % SE_MSG_WORD_SZ) { + pr_err("Msg-len is not 4-byte aligned.\n"); + return -EINVAL; + } + + nb_words = msg_len / sizeof(*msg); + if (nb_words < 5) + return -EINVAL; + + /* Last word is the checksum word, so skip it. */ + nb_words--; + + for (i = 0; i < nb_words; i++) + chksum ^= msg[i]; + + msg[nb_words] = chksum; + + return 0; +} + +/** + * ele_msg_rcv() - wait for a response from the secure enclave. + * @priv: pointer to the SE interface private data. + * @se_clbk_hdl: callback handle whose completion will be signaled when the + * response arrives. + * + * Blocks until the firmware delivers a response into the buffer registered + * in @se_clbk_hdl, or until the per-interface timeout expires. When waiting + * on the response path a deadline is enforced; on timeout the firmware-busy + * circuit breaker is armed to prevent further transactions until the delayed + * response arrives and clears it. + * + * Return: number of bytes received on success, negative errno on error + * (e.g. -ETIMEDOUT, -ERESTARTSYS). + */ +int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl) +{ + bool is_rsp_wait_with_timeout = false; + bool wait_uninterruptible = false; + unsigned long remaining_jiffies; + unsigned long deadline_jiffies; + unsigned long flags; + int ret; + + remaining_jiffies = msecs_to_jiffies(SE_RCV_MSG_DEFAULT_TIMEOUT_MS); + if (se_clbk_hdl == &priv->waiting_rsp_clbk_hdl) { + is_rsp_wait_with_timeout = true; + deadline_jiffies = jiffies + remaining_jiffies; + } + + do { + if (is_rsp_wait_with_timeout) { + unsigned long now = jiffies; + + if (time_after_eq(now, deadline_jiffies)) { + /* Deadline hit: fence hung FW, like the ret==0 path. */ + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + se_clbk_hdl->rx_msg = NULL; + if (!completion_done(&se_clbk_hdl->done)) + atomic_set(&priv->fw_busy, 1); + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + ret = -ETIMEDOUT; + break; + } + remaining_jiffies = deadline_jiffies - now; + } + + if (wait_uninterruptible) + ret = wait_for_completion_timeout(&se_clbk_hdl->done, + remaining_jiffies); + else + ret = wait_for_completion_interruptible_timeout(&se_clbk_hdl->done, + remaining_jiffies); + if (ret == -ERESTARTSYS) { + /* + * Record that a signal was observed, then continue waiting non- + * interruptibly until the response arrives or the timeout + * expires. The caller can surface the interruption to userspace + * after the protocol transaction is brought back to a + * synchronized state. + */ + if (is_rsp_wait_with_timeout && + READ_ONCE(se_clbk_hdl->rx_msg)) { + WRITE_ONCE(se_clbk_hdl->signal_rcvd, true); + wait_uninterruptible = true; + continue; + } + break; + } + + if (ret == 0) { + /* + * The response buffer belongs to the caller of ele_msg_send_rcv() + * and may be freed as soon as this function returns. Clear rx_msg + * under clbk_rx_lock so that a late se_if_rx_callback() can + * observe that the waiter has timed out and must not copy into + * the stale buffer. + * + * If the completion has not yet been signaled, mark the firmware + * path busy. This acts as a circuit breaker: reject new + * command/response transactions until the delayed response + * arrives and the callback closes the breaker. + */ + + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + se_clbk_hdl->rx_msg = NULL; + if (!completion_done(&se_clbk_hdl->done)) + atomic_set(&priv->fw_busy, 1); + + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + ret = -ETIMEDOUT; + dev_err(priv->dev, + "Fatal Error: SE interface %s0, hangs indefinitely.\n", + get_se_if_name(priv->if_defs->se_if_type)); + break; + } + ret = se_clbk_hdl->rx_msg_sz; + break; + } while (ret < 0); + + return ret; +} + +/** + * ele_msg_send() - send a message to the secure enclave over the mailbox. + * @priv: pointer to the SE interface private data. + * @tx_msg: buffer containing the message to send. + * @tx_msg_sz: size of @tx_msg in bytes; must match the size field in the + * message header. + * + * Copies the message into the MU TX registers via the mailbox framework. + * The MU controller does not retain the caller's buffer after this call + * returns, so the caller may free @tx_msg immediately on success. + * + * Return: @tx_msg_sz on success, negative errno on error. + */ +int ele_msg_send(struct se_if_priv *priv, + void *tx_msg, + int tx_msg_sz) +{ + struct se_msg_hdr *header = tx_msg; + int err; + + /* + * Check that the size passed as argument matches the size + * carried in the message. + */ + if (header->size << 2 != tx_msg_sz) { + dev_err(priv->dev, + "User buf hdr: 0x%x, sz mismatched with input-sz (%d != %d).\n", + *(u32 *)header, header->size << 2, tx_msg_sz); + return -EINVAL; + } + + /* + * The i.MX MU mailbox controller copies the payload words into MU + * registers synchronously from its send path. It does not retain the + * caller-provided tx_msg pointer after mbox_send_message() returns, so + * the caller-owned buffer may be released after a successful send. + */ + err = mbox_send_message(priv->tx_chan, tx_msg); + if (err < 0) { + dev_err(priv->dev, "Error: mbox_send_message failure.\n"); + return err; + } + + return tx_msg_sz; +} + +static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + priv->waiting_rsp_clbk_hdl.rx_msg = NULL; + priv->waiting_rsp_clbk_hdl.rx_msg_sz = 0; + spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); +} + +/** + * ele_msg_send_rcv() - send a command and wait for the response. + * @priv: pointer to the SE interface private data. + * @tx_msg: buffer containing the command message to send. + * @tx_msg_sz: size of @tx_msg in bytes. + * @rx_msg: caller-provided buffer to receive the response into. + * @exp_rx_msg_sz: expected response size in bytes. + * + * Holds the SE command lock for the duration of the exchange to prevent + * concurrent transactions. Signals are deferred until the protocol + * resynchronizes; -ERESTARTSYS is returned to the caller after a clean + * response is received if a signal arrived during the wait. + * + * Return: number of bytes received on success, negative errno on error. + */ +int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz, + void *rx_msg, int exp_rx_msg_sz) +{ + unsigned long flags; + int err; + + guard(mutex)(&priv->se_if_cmd_lock); + + if (atomic_read(&priv->fw_busy)) { + dev_dbg(priv->dev, "ELE became unresponsive.\n"); + return -EBUSY; + } + reinit_completion(&priv->waiting_rsp_clbk_hdl.done); + /* Publish rx_msg/rx_msg_sz under the lock read by se_if_rx_callback(). */ + spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz; + priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg; + spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + + err = ele_msg_send(priv, tx_msg, tx_msg_sz); + if (err < 0) { + ele_msg_send_rcv_cleanup(priv); + return err; + } + + err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl); + + if (priv->waiting_rsp_clbk_hdl.signal_rcvd) { + /* + * Signal was deferred until the FW/kernel protocol resynchronized. + * On success report -ERESTARTSYS for the interrupted wait; the + * command is not re-sent. Keep real errors like -ETIMEDOUT. + */ + if (err > 0) + err = -ERESTARTSYS; + priv->waiting_rsp_clbk_hdl.signal_rcvd = false; + dev_dbg(priv->dev, "Err[0x%x]:Interrupted by signal.\n", err); + } + + ele_msg_send_rcv_cleanup(priv); + + return err; +} + +static bool check_hdr_exception_for_sz(struct se_if_priv *priv, + struct se_msg_hdr *header) +{ + /* + * List of API headers that can accept a variable length response buffer. + */ + if (header->command == ELE_DEBUG_DUMP_REQ && + header->ver == priv->if_defs->base_api_ver && + header->size >= 2 && header->size <= (ELE_DEBUG_DUMP_RSP_SZ / 4)) + return true; + + return false; +} + +/** + * se_if_rx_callback() - mailbox RX callback for secure enclave messages. + * @mbox_cl: mailbox client registered for this SE interface. + * @msg: pointer to the received message buffer; may be NULL or an ERR_PTR. + * + * Dispatches the incoming message to either the command receiver (cmd_tag) + * or the synchronous response waiter (rsp_tag). Called from mailbox IRQ + * context; must not sleep. + */ +void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) +{ + struct se_clbk_handle *se_clbk_hdl; + struct device *dev = mbox_cl->dev; + struct se_msg_hdr *header; + bool sz_mismatch = false; + struct se_if_priv *priv; + unsigned long flags; + u32 rx_msg_sz; + + priv = dev_get_drvdata(dev); + if (!priv) + return; + + /* The function can be called with NULL msg */ + if (IS_ERR_OR_NULL(msg)) { + dev_err(dev, "Message is invalid\n"); + return; + } + + header = msg; + rx_msg_sz = header->size << 2; + + /* Incoming command: wake up the receiver if any. */ + if (header->tag == priv->if_defs->cmd_tag) { + se_clbk_hdl = &priv->cmd_receiver_clbk_hdl; + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + if (!se_clbk_hdl->rx_msg) { + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + dev_warn(dev, "No command receiver registered for message: %.8x\n", + *((u32 *)header)); + return; + } + + /* + * cmd_tag messages are delivered only to the explicitly registered + * command receiver. Unlike the synchronous response waiter path, the + * command receiver uses a dedicated long-lived buffer installed by + * SE_IOCTL_ENABLE_CMD_RCV and is not subject to the timeout/circuit- + * breaker handling used for rsp_tag messages. + */ + dev_dbg(dev, "Selecting cmd receiver: for mesg header:0x%x.\n", + *(u32 *)header); + + /* + * Pre-allocated buffer of MAX_NVM_MSG_LEN + * as the NVM command are initiated by FW. + * Size is revealed as part of this call function. + */ + + if (rx_msg_sz > MAX_NVM_MSG_LEN) + sz_mismatch = true; + + /* + * Clamp the copy length to the pre-allocated receiver buffer (MAX_NVM_MSG_LEN). + */ + se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, MAX_NVM_MSG_LEN); + memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz); + complete(&se_clbk_hdl->done); + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + if (sz_mismatch) + dev_err(dev, + "CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n", + *(u32 *)header, + (header->size << 2), rx_msg_sz); + } else if (header->tag == priv->if_defs->rsp_tag) { + bool exception_for_sz_mismatch = check_hdr_exception_for_sz(priv, header); + u32 exp_rx_msg_sz; + + /* + * rx_msg and rx_msg_sz are owned by the sender under clbk_rx_lock. + * Read both under the lock: drop a late response instead of copying + * into freed memory, and avoid a stale size. A late response also + * closes the firmware-busy circuit breaker. + */ + se_clbk_hdl = &priv->waiting_rsp_clbk_hdl; + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + if (!se_clbk_hdl->rx_msg) { + /* Close circuit breaker on spinlock race */ + atomic_set(&priv->fw_busy, 0); + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + dev_info(dev, "ELE responded (late), recovery FW available.\n"); + return; + } + exp_rx_msg_sz = se_clbk_hdl->rx_msg_sz; + dev_dbg(dev, "Selecting resp waiter: for mesg header:0x%x.\n", + *(u32 *)header); + + /* + * For rsp_tag traffic, the sender provides the expected response + * buffer size. If firmware returns a different size, clamp the copy + * length to the caller's buffer capacity before memcpy() and report the + * mismatch after dropping the spinlock. + */ + if (rx_msg_sz != exp_rx_msg_sz && !exception_for_sz_mismatch) + sz_mismatch = true; + + se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, exp_rx_msg_sz); + memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz); + complete(&se_clbk_hdl->done); + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + + if (sz_mismatch) + dev_err(dev, + "Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n", + *(u32 *)header, + (header->size << 2), exp_rx_msg_sz); + } else { + dev_err(dev, "Failed to select a device for message: %.8x\n", + *((u32 *)header)); + } +} + +/** + * se_val_rsp_hdr_n_status() - validate a response message header and status. + * @priv: pointer to the SE interface private data. + * @msg: response message buffer to validate. + * @msg_id: expected command identifier. + * @sz: expected message size in bytes. + * @version: expected API version byte from the command message header + * (tx_msg->header.ver); the response header->ver must match this + * value exactly. + * + * Checks the response tag, command id, API version, status word, and + * response size. The size check is performed after the status check so that + * a well-formed response whose FW-declared size differs from the userspace + * buffer size still has its status extracted and its FW handle recorded. + * Size mismatch returns -ENOSPC (not -EINVAL) so callers can distinguish it + * from a header field mismatch and still run fw_api_specific_ops(). + * + * Return: 0 on success, -EINVAL if tag/command/version mismatch, -EPERM if + * the firmware status indicates a command failure, -ENOSPC if the response + * size does not match @sz. + */ +int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg, + u8 msg_id, u8 sz, u8 version) +{ + struct se_msg_hdr *header = &msg->header; + u32 status; + + if (header->tag != priv->if_defs->rsp_tag) { + dev_dbg(priv->dev, "MSG[0x%x] Hdr: Resp tag mismatch. (0x%x != 0x%x)\n", + msg_id, header->tag, priv->if_defs->rsp_tag); + return -EINVAL; + } + + if (header->command != msg_id) { + dev_dbg(priv->dev, "MSG Header: Cmd id mismatch. (0x%x != 0x%x)\n", + header->command, msg_id); + return -EINVAL; + } + + if (header->ver != version) { + dev_dbg(priv->dev, + "MSG[0x%x] Hdr: API Vers mismatch. (0x%x != 0x%x)\n", + msg_id, header->ver, version); + return -EINVAL; + } + + if (header->size > SE_MU_HDR_WORD_SZ && (sz >> 2) > SE_MU_HDR_WORD_SZ) { + status = RES_STATUS(msg->data[0]); + if (status != priv->if_defs->success_tag) { + dev_dbg(priv->dev, "Command Id[%x], Response Failure = 0x%x\n", + header->command, status); + return -EPERM; + } + } + + if ((sz % 4) || (header->size != (sz >> 2) && + !check_hdr_exception_for_sz(priv, header))) { + dev_dbg(priv->dev, "MSG[0x%x] Hdr: Cmd size mismatch. (0x%x != 0x%x)\n", + msg_id, header->size, (sz >> 2)); + return -ENOSPC; + } + + return 0; +} + +/** + * se_save_imem_state() - export and save the encrypted IMEM state. + * @priv: pointer to the SE interface private data. + * @imem: IMEM buffer descriptor; @imem->daddr must point to a DMA-coherent + * buffer of at least ELE_IMEM_SIZE bytes. + * + * Issues an ELE_IMEM_EXPORT service-swap command to save the current IMEM + * content into the pre-allocated DMA buffer. Intended to be called during + * system suspend. + * + * Return: 0 on success, negative errno on failure. + */ +int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem) +{ + struct ele_dev_info s_info = {0}; + int ret; + + ret = ele_get_info(priv, &s_info); + if (ret) { + dev_err(priv->dev, "Failed to get info from ELE.\n"); + return ret; + } + + /* Check for the imem-state before continue to save imem state. */ + if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_BAD) + return 0; + + /* + * EXPORT command will save encrypted IMEM to given address, + * so later in resume, IMEM can be restored from the given + * address. + * + * Size must be at least 64 kB. + */ + ret = ele_service_swap(priv, imem->daddr, ELE_IMEM_SIZE, ELE_IMEM_EXPORT); + if (ret < 0) { + dev_err(priv->dev, "Failed to export IMEM.\n"); + imem->size = 0; + } else if (ret > ELE_IMEM_SIZE) { + dev_err(priv->dev, "Invalid exported IMEM size %d.\n", ret); + imem->size = 0; + ret = -EIO; + } else { + dev_dbg(priv->dev, + "Exported %d bytes of encrypted IMEM.\n", + ret); + imem->size = ret; + } + + return ret > 0 ? 0 : ret; +} + +/** + * se_restore_imem_state() - restore the encrypted IMEM state after resume. + * @priv: pointer to the SE interface private data. + * @imem: IMEM buffer descriptor populated by a prior se_save_imem_state() + * call; @imem->size must be non-zero. + * + * Issues an ELE_IMEM_IMPORT service-swap command to restore IMEM from the + * saved DMA buffer, then verifies that the enclave reports + * ELE_IMEM_STATE_OK. Intended to be called during system resume. + * + * Return: 0 on success, -EIO if IMEM state is not OK after import, or + * another negative errno on communication failure. + */ +int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem) +{ + struct ele_dev_info s_info; + int ret; + + /* get info from ELE */ + ret = ele_get_info(priv, &s_info); + if (ret) { + dev_err(priv->dev, "Failed to get info from ELE.\n"); + return ret; + } + imem->state = s_info.d_addn_info.imem_state; + + /* Check for the imem-state and imem-size before continue to + * restore imem state. + */ + if (s_info.d_addn_info.imem_state != ELE_IMEM_STATE_BAD || !imem->size) + return 0; + + /* + * IMPORT command will restore IMEM from the given + * address, here size is the actual size returned by ELE + * during the export operation + */ + ret = ele_service_swap(priv, imem->daddr, imem->size, ELE_IMEM_IMPORT); + if (ret) { + dev_err(priv->dev, "Failed to import IMEM\n"); + return ret; + } + + /* + * After importing IMEM, check if IMEM state is equal to 0xCA + * to ensure IMEM is fully loaded and + * ELE functionality can be used. + */ + ret = ele_get_info(priv, &s_info); + if (ret) { + dev_err(priv->dev, "Failed to get info from ELE.\n"); + return ret; + } + imem->state = s_info.d_addn_info.imem_state; + + if (s_info.d_addn_info.imem_state == ELE_IMEM_STATE_OK) { + dev_dbg(priv->dev, "Successfully restored IMEM.\n"); + } else { + dev_err(priv->dev, "Failed to restore IMEM: state=0x%02x, expected 0x%02x.\n", + s_info.d_addn_info.imem_state, ELE_IMEM_STATE_OK); + /* + * ele_get_info() succeeded (ret == 0) but the IMEM state + * reported by the hardware is not ELE_IMEM_STATE_OK. Return + * -EIO so the PM subsystem knows the enclave is non-functional + * after resume, instead of silently continuing with bad state. + */ + ret = -EIO; + } + + return ret; +} diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h new file mode 100644 index 000000000000..39bba4ebe8b7 --- /dev/null +++ b/drivers/firmware/imx/ele_common.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2025 NXP + */ + +#ifndef __ELE_COMMON_H__ +#define __ELE_COMMON_H__ + +#include "se_ctrl.h" + +#define SE_RCV_MSG_DEFAULT_TIMEOUT_MS 3000 + +#define ELE_SUCCESS_IND 0xD6 + +#define IMX_ELE_FW_DIR "imx/ele/" + +int se_update_msg_chksum(u32 *msg, u32 msg_len); + +int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl); + +int ele_msg_send(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz); + +int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz, + void *rx_msg, int exp_rx_msg_sz); + +void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg); + +int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg, + u8 msg_id, u8 sz, u8 version); + +/* Fill a command message header with a given command ID and length in bytes. */ +static inline void se_fill_cmd_msg_hdr(struct se_if_priv *priv, struct se_msg_hdr *hdr, + u8 cmd, u32 len, bool is_base_api) +{ + hdr->tag = priv->if_defs->cmd_tag; + hdr->ver = (is_base_api) ? priv->if_defs->base_api_ver : priv->if_defs->fw_api_ver; + hdr->command = cmd; + hdr->size = len >> 2; +} + +int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem); + +int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem); + +#endif /*__ELE_COMMON_H__ */ diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c new file mode 100644 index 000000000000..0013c960ec43 --- /dev/null +++ b/drivers/firmware/imx/se_ctrl.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2026 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ele_base_msg.h" +#include "ele_common.h" +#include "se_ctrl.h" + +#define MAX_SOC_INFO_DATA_SZ 256 +#define SE_TYPE_STR_DBG "dbg" +#define SE_TYPE_STR_HSM "hsm" + +#define SE_TYPE_ID_DBG 0x1 + +#define SE_TYPE_ID_HSM 0x2 + +struct se_soc_dev_regn { + bool soc_dev_registered; + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; +}; + +struct se_var_info { + u16 soc_rev; + struct se_soc_dev_regn soc_dev_regn; + /* To serialize populating common SoC level info. */ + struct mutex se_var_info_lock; +}; + +/* contains fixed information */ +struct se_soc_info { + const u16 soc_id; + const char *soc_name; + const struct se_fw_img_name se_fw_img_nm; + bool imem_state_mgmt; +}; + +struct se_if_node { + struct se_soc_info *se_info; + u8 *pool_name; + bool reserved_dma_ranges; + struct se_if_defines if_defs; +}; + +/* common for all the SoC. */ +static struct se_var_info var_se_info = { + .soc_rev = 0, + .se_var_info_lock = __MUTEX_INITIALIZER(var_se_info.se_var_info_lock) +}; + +static struct se_soc_info se_imx8ulp_info = { + .soc_id = SOC_ID_OF_IMX8ULP, + .soc_name = "i.MX8ULP", + .se_fw_img_nm = { + .prim_fw_nm_in_rfs = IMX_ELE_FW_DIR + "mx8ulpa2-ahab-container.img", + .seco_fw_nm_in_rfs = IMX_ELE_FW_DIR + "mx8ulpa2ext-ahab-container.img", + }, + .imem_state_mgmt = true, +}; + +static struct se_if_node imx8ulp_se_ele_hsm = { + .se_info = &se_imx8ulp_info, + .pool_name = "sram", + .reserved_dma_ranges = true, + .if_defs = { + .se_if_type = SE_TYPE_ID_HSM, + .cmd_tag = 0x17, + .rsp_tag = 0xe1, + .success_tag = ELE_SUCCESS_IND, + .base_api_ver = MESSAGING_VERSION_6, + .fw_api_ver = MESSAGING_VERSION_7, + }, +}; + +static struct se_soc_info se_imx93_info = { + .soc_id = SOC_ID_OF_IMX93, +}; + +static struct se_if_node imx93_se_ele_hsm = { + .se_info = &se_imx93_info, + .reserved_dma_ranges = true, + .if_defs = { + .se_if_type = SE_TYPE_ID_HSM, + .cmd_tag = 0x17, + .rsp_tag = 0xe1, + .success_tag = ELE_SUCCESS_IND, + .base_api_ver = MESSAGING_VERSION_6, + .fw_api_ver = MESSAGING_VERSION_7, + }, +}; + +static const struct of_device_id se_match[] = { + { .compatible = "fsl,imx8ulp-se-ele-hsm", .data = &imx8ulp_se_ele_hsm }, + { .compatible = "fsl,imx93-se-ele-hsm", .data = &imx93_se_ele_hsm }, + { } +}; +MODULE_DEVICE_TABLE(of, se_match); + +/** + * get_se_if_name() - return a human-readable string for a SE interface type. + * @se_if_id: SE interface type identifier (e.g. SE_TYPE_ID_HSM). + * + * Return: pointer to a constant string naming the interface type, or "unknown" + * if @se_if_id does not match any known type. + */ +char *get_se_if_name(u8 se_if_id) +{ + switch (se_if_id) { + case SE_TYPE_ID_DBG: return SE_TYPE_STR_DBG; + case SE_TYPE_ID_HSM: return SE_TYPE_STR_HSM; + } + + return "unknown"; +} + +static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv) +{ + return &priv->load_fw; +} + +static void se_soc_device_unregister(struct se_soc_dev_regn *soc_dev_regn) +{ + guard(mutex)(&var_se_info.se_var_info_lock); + + if (soc_dev_regn->soc_dev) { + soc_device_unregister(soc_dev_regn->soc_dev); + soc_dev_regn->soc_dev = NULL; + } + + if (soc_dev_regn->soc_dev_attr) { + /* + * revision and serial_number are the only kasprintf()-allocated + * strings. machine points into the DT, and soc_id/family are + * constants, so they must not be freed. + */ + kfree(soc_dev_regn->soc_dev_attr->revision); + kfree(soc_dev_regn->soc_dev_attr->serial_number); + kfree(soc_dev_regn->soc_dev_attr); + soc_dev_regn->soc_dev_attr = NULL; + } + + soc_dev_regn->soc_dev_registered = false; +} + +/* + * Build and register a soc_device entry for this SoC. Separated from + * get_se_soc_info() so that the firmware-fetch path and the sysfs + * registration path can be reasoned about independently. + */ +static int se_soc_dev_register(struct se_if_priv *priv, u16 soc_rev, + const char *soc_name, const u8 *uid) +{ + struct soc_device_attribute *attr; + struct soc_device *sdev; + int err; + + if (!soc_rev || !soc_name || !uid) + return -EINVAL; + + attr = kzalloc_obj(*attr); + if (!attr) + return -ENOMEM; + + if (FIELD_GET(DEV_GETINFO_MIN_VER_MASK, soc_rev)) + attr->revision = kasprintf(GFP_KERNEL, "%x.%x", + FIELD_GET(DEV_GETINFO_MAJ_VER_MASK, soc_rev), + FIELD_GET(DEV_GETINFO_MIN_VER_MASK, soc_rev)); + else + attr->revision = kasprintf(GFP_KERNEL, "%x", + FIELD_GET(DEV_GETINFO_MAJ_VER_MASK, soc_rev)); + + if (!attr->revision) { + err = -ENOMEM; + goto err_free_attr; + } + + attr->soc_id = soc_name; + + err = of_property_read_string(of_root, "model", &attr->machine); + if (err) { + err = -EINVAL; + goto err_free_rev; + } + + attr->family = "Freescale i.MX"; + + attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", + GET_SERIAL_NUM_FROM_UID(uid, MAX_UID_SIZE >> 2)); + if (!attr->serial_number) { + err = -ENOMEM; + goto err_free_rev; + } + + sdev = soc_device_register(attr); + if (IS_ERR(sdev)) { + err = PTR_ERR(sdev); + goto err_free_serial; + } + + /* + * Publish the singleton. Freed once, at module unload, by + * se_soc_device_unregister(). Caller holds se_var_info_lock. + */ + var_se_info.soc_dev_regn.soc_dev = sdev; + var_se_info.soc_dev_regn.soc_dev_attr = attr; + + /* Mark registration complete so get_se_soc_info() skips this path on retry. */ + var_se_info.soc_dev_regn.soc_dev_registered = true; + + return 0; + +err_free_serial: + kfree(attr->serial_number); +err_free_rev: + kfree(attr->revision); +err_free_attr: + kfree(attr); + + return err; +} + +static int get_se_soc_info(struct se_if_priv *priv, const struct se_soc_info *se_info) +{ + struct se_fw_load_info *load_fw = get_load_fw_instance(priv); + u8 data[MAX_SOC_INFO_DATA_SZ]; + struct ele_dev_info *s_info; + int err; + + guard(mutex)(&var_se_info.se_var_info_lock); + + /* + * Early exit: both objectives already complete, nothing to do. + * Do not exit early when imem_mgmt is active: load_fw is per-probe + * (embedded in priv) and starts zeroed on every probe, so imem.state + * must be refreshed from firmware on each probe even when soc_rev is + * already cached in the module-lifetime var_se_info. + */ + if (var_se_info.soc_rev && + (!se_info->soc_name || var_se_info.soc_dev_regn.soc_dev_registered) && + !load_fw->imem_mgmt) + return 0; + + err = ele_fetch_soc_info(priv, &data); + if (err < 0) + return dev_err_probe(priv->dev, err, "Failed to fetch SoC Info.\n"); + + s_info = (struct ele_dev_info *)data; + + if (!var_se_info.soc_rev) + var_se_info.soc_rev = s_info->d_info.soc_rev; + + /* + * imem.state is per-probe state (lives in priv->load_fw which is + * zeroed on every probe). Update it unconditionally whenever the + * IMEM management path is active, regardless of whether soc_rev was + * already cached from a previous probe or a sibling interface. + */ + if (load_fw->imem_mgmt) + load_fw->imem.state = s_info->d_addn_info.imem_state; + + if (se_info->soc_name && !var_se_info.soc_dev_regn.soc_dev_registered) { + err = se_soc_dev_register(priv, var_se_info.soc_rev, + se_info->soc_name, s_info->d_info.uid); + if (err < 0) + return dev_err_probe(priv->dev, err, + "Failed to register SE SoC device.\n"); + } + + return 0; +} + +static int se_if_request_channel(struct device *dev, struct mbox_chan **chan, + struct mbox_client *cl, const char *name) +{ + struct mbox_chan *t_chan; + + t_chan = mbox_request_channel_byname(cl, name); + if (IS_ERR(t_chan)) + return dev_err_probe(dev, PTR_ERR(t_chan), + "Failed to request %s channel.\n", name); + + *chan = t_chan; + + return 0; +} + +static void se_if_probe_cleanup(void *plat_dev) +{ + struct platform_device *pdev = plat_dev; + struct device *dev = &pdev->dev; + struct se_if_priv *priv; + + priv = dev_get_drvdata(dev); + if (!priv) + return; + + if (priv->rx_chan) + mbox_free_channel(priv->rx_chan); + if (priv->tx_chan) + mbox_free_channel(priv->tx_chan); + + /* + * Being device managed buffer, no need to free the buffer allocated + * in se probe to store encrypted IMEM. + */ + + /* + * No need to check, if reserved memory is allocated + * before calling for its release. Or clearing the + * un-set bit. + */ + of_reserved_mem_device_release(dev); + + dev_set_drvdata(dev, NULL); + mutex_destroy(&priv->load_fw.load_fw_lock); + mutex_destroy(&priv->se_if_cmd_lock); + kfree(priv); +} + +static int se_if_probe(struct platform_device *pdev) +{ + const struct se_soc_info *se_info; + const struct se_if_node *if_node; + struct device *dev = &pdev->dev; + struct se_fw_load_info *load_fw; + struct se_if_priv *priv; + int ret; + + if_node = device_get_match_data(dev); + if (!if_node) + return -EINVAL; + + se_info = if_node->se_info; + + priv = kzalloc_obj(*priv); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->if_defs = &if_node->if_defs; + dev_set_drvdata(dev, priv); + + spin_lock_init(&priv->cmd_receiver_clbk_hdl.clbk_rx_lock); + spin_lock_init(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock); + atomic_set(&priv->fw_busy, 0); + init_completion(&priv->waiting_rsp_clbk_hdl.done); + init_completion(&priv->cmd_receiver_clbk_hdl.done); + + mutex_init(&priv->se_if_cmd_lock); + + load_fw = get_load_fw_instance(priv); + mutex_init(&load_fw->load_fw_lock); + if (se_info->se_fw_img_nm.seco_fw_nm_in_rfs) { + load_fw->se_fw_img_nm = &se_info->se_fw_img_nm; + load_fw->is_fw_tobe_loaded = true; + } + ret = devm_add_action_or_reset(dev, se_if_probe_cleanup, pdev); + if (ret) + return ret; + + /* Mailbox client configuration */ + priv->se_mb_cl.dev = dev; + priv->se_mb_cl.tx_block = false; + priv->se_mb_cl.knows_txdone = false; + priv->se_mb_cl.rx_callback = se_if_rx_callback; + + ret = se_if_request_channel(dev, &priv->tx_chan, &priv->se_mb_cl, "tx"); + if (ret) + return ret; + + ret = se_if_request_channel(dev, &priv->rx_chan, &priv->se_mb_cl, "rx"); + if (ret) + return ret; + + if (if_node->pool_name) { + priv->mem_pool = of_gen_pool_get(dev->of_node, if_node->pool_name, 0); + if (!priv->mem_pool) + return dev_err_probe(dev, -ENOMEM, + "Unable to get sram pool = %s.\n", + if_node->pool_name); + } + + if (if_node->reserved_dma_ranges) { + ret = of_reserved_mem_device_init(dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to init reserved memory region.\n"); + } + + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + + /* By default, there is no pending FW to be loaded.*/ + if (se_info->imem_state_mgmt) { + /* allocate buffer where SE store encrypted IMEM */ + load_fw->imem.buf = dmam_alloc_coherent(priv->dev, ELE_IMEM_SIZE, + &load_fw->imem.daddr, + GFP_KERNEL); + if (!load_fw->imem.buf) + return dev_err_probe(dev, -ENOMEM, + "dmam-alloc-failed: To store encr-IMEM.\n"); + load_fw->imem_mgmt = true; + } + + if (if_node->if_defs.se_if_type == SE_TYPE_ID_HSM) { + ret = get_se_soc_info(priv, se_info); + if (ret) + return dev_err_probe(dev, ret, "Failed to fetch SoC Info.\n"); + } + + dev_info(dev, "i.MX secure-enclave: %s0 interface to firmware, configured.\n", + get_se_if_name(priv->if_defs->se_if_type)); + + return ret; +} + +static int se_suspend(struct device *dev) +{ + struct se_if_priv *priv = dev_get_drvdata(dev); + struct se_fw_load_info *load_fw; + unsigned int noio_flag; + int ret = 0; + + load_fw = get_load_fw_instance(priv); + + if (load_fw->imem_mgmt) { + /* + * Set PF_MEMALLOC_NOIO for the duration of the suspend + * callbacks. This covers all allocations in the call chain + * (ele_get_info, se_service_swap, se_get_mem_pool_buf) without + * requiring each site to pass GFP_NOIO explicitly. Without this, + * GFP_KERNEL allocations in those paths could trigger direct + * reclaim and attempt I/O to a storage device that is already + * suspended, causing a deadlock. + */ + noio_flag = memalloc_noio_save(); + ret = se_save_imem_state(priv, &load_fw->imem); + memalloc_noio_restore(noio_flag); + if (ret) + dev_err(dev, "Failure saving IMEM state[0x%x]\n", ret); + } + + return ret; +} + +static int se_resume(struct device *dev) +{ + struct se_if_priv *priv = dev_get_drvdata(dev); + struct se_fw_load_info *load_fw; + unsigned int noio_flag; + int ret = 0; + + load_fw = get_load_fw_instance(priv); + + if (load_fw->imem_mgmt) { + noio_flag = memalloc_noio_save(); + ret = se_restore_imem_state(priv, &load_fw->imem); + memalloc_noio_restore(noio_flag); + if (ret) + dev_err(dev, "Failure restoring IMEM state[0x%x]\n", ret); + } + + return ret; +} + +DEFINE_SIMPLE_DEV_PM_OPS(se_pm, se_suspend, se_resume); + +static struct platform_driver se_driver = { + .driver = { + .name = "fsl-se", + .of_match_table = se_match, + .pm = pm_sleep_ptr(&se_pm), + }, + .probe = se_if_probe, +}; + +static int __init se_init(void) +{ + return platform_driver_register(&se_driver); +} +module_init(se_init); + +static void __exit se_exit(void) +{ + platform_driver_unregister(&se_driver); + + /* + * The soc_device is a module-scoped singleton that outlives any single + * MU interface bind/unbind. Release it here, once, after every interface + * has been unbound, so its lifetime is tied to the module rather than to + * the first-probed interface. + */ + se_soc_device_unregister(&var_se_info.soc_dev_regn); +} +module_exit(se_exit); + +MODULE_AUTHOR("Pankaj Gupta "); +MODULE_DESCRIPTION("iMX Secure Enclave Driver."); +MODULE_LICENSE("GPL"); diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h new file mode 100644 index 000000000000..54b2a262a2c3 --- /dev/null +++ b/drivers/firmware/imx/se_ctrl.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2026 NXP + */ + +#ifndef SE_CTRL_H +#define SE_CTRL_H + +#include +#include +#include +#include + +#define MAX_FW_LOAD_RETRIES 50 +#define SE_MSG_WORD_SZ 0x4 + +#define RES_STATUS(x) FIELD_GET(0x000000ff, x) +#define MAX_NVM_MSG_LEN (256) +#define MESSAGING_VERSION_6 0x6 +#define MESSAGING_VERSION_7 0x7 + +struct se_clbk_handle { + struct completion done; + bool signal_rcvd; + u32 rx_msg_sz; + /* + * Assignment of the rx_msg buffer to held till the + * received content as part callback function, is copied. + */ + struct se_api_msg *rx_msg; + /* + * Serialise the timeout path in ele_msg_rcv() against + * se_if_rx_callback() so that the callback can never + * memcpy into a buffer that the timeout path has already + * freed. + */ + spinlock_t clbk_rx_lock; +}; + +struct se_imem_buf { + u8 *buf; + dma_addr_t daddr; + u32 size; + u32 state; +}; + +/* Header of the messages exchange with the EdgeLock Enclave */ +struct se_msg_hdr { + u8 ver; + u8 size; + u8 command; + u8 tag; +} __packed; + +#define SE_MU_HDR_SZ 4 +#define SE_MU_HDR_WORD_SZ 1 + +struct se_api_msg { + struct se_msg_hdr header; + u32 data[]; +}; + +struct se_if_defines { + const u8 se_if_type; + u8 cmd_tag; + u8 rsp_tag; + u8 success_tag; + u8 base_api_ver; + u8 fw_api_ver; +}; + +struct se_fw_img_name { + const char *prim_fw_nm_in_rfs; + const char *seco_fw_nm_in_rfs; +}; + +struct se_fw_load_info { + const struct se_fw_img_name *se_fw_img_nm; + bool is_fw_tobe_loaded; + bool imem_mgmt; + struct se_imem_buf imem; + /* to serialize the fw load state */ + struct mutex load_fw_lock; +}; + +struct se_if_priv { + struct device *dev; + + struct se_clbk_handle cmd_receiver_clbk_hdl; + /* + * Update to the waiting_rsp_dev, to be protected + * under se_if_cmd_lock. + */ + struct se_clbk_handle waiting_rsp_clbk_hdl; + /* + * prevent new command to be sent on the se interface while previous + * command is still processing. (response is awaited) + */ + struct mutex se_if_cmd_lock; + + struct mbox_client se_mb_cl; + struct mbox_chan *tx_chan, *rx_chan; + + struct gen_pool *mem_pool; + const struct se_if_defines *if_defs; + struct se_fw_load_info load_fw; + + atomic_t fw_busy; +}; + +char *get_se_if_name(u8 se_if_id); +#endif diff --git a/include/linux/firmware/imx/se_api.h b/include/linux/firmware/imx/se_api.h new file mode 100644 index 000000000000..b1c4c9115d7b --- /dev/null +++ b/include/linux/firmware/imx/se_api.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2025 NXP + */ + +#ifndef __SE_API_H__ +#define __SE_API_H__ + +#include + +#define SOC_ID_OF_IMX8ULP 0x084d +#define SOC_ID_OF_IMX93 0x9300 + +#endif /* __SE_API_H__ */ -- cgit v1.2.3 From 5be22027cdb5773d474514212f20730b69664572 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:10:01 +0530 Subject: firmware: imx: device context dedicated to priv Add priv_dev_ctx to prepare enabling misc-device context based send-receive path, to communicate with FW. No functionality change. Signed-off-by: Pankaj Gupta Reviewed-by: Frank Li Signed-off-by: Frank Li --- drivers/firmware/imx/ele_base_msg.c | 25 ++++++------- drivers/firmware/imx/ele_common.c | 71 +++++++++++++++++++++++-------------- drivers/firmware/imx/ele_common.h | 10 +++--- drivers/firmware/imx/se_ctrl.c | 34 ++++++++++++++++++ drivers/firmware/imx/se_ctrl.h | 9 +++++ 5 files changed, 105 insertions(+), 44 deletions(-) diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c index dba6f0ee83ed..650153d39f46 100644 --- a/drivers/firmware/imx/ele_base_msg.c +++ b/drivers/firmware/imx/ele_base_msg.c @@ -82,14 +82,15 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) tx_msg->data[0] = upper_32_bits(get_info_addr); tx_msg->data[1] = lower_32_bits(get_info_addr); tx_msg->data[2] = sizeof(*s_info); - ret = ele_msg_send_rcv(priv, tx_msg, ELE_GET_INFO_REQ_MSG_SZ, rx_msg, - ELE_GET_INFO_RSP_MSG_SZ); + + ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_GET_INFO_REQ_MSG_SZ, + rx_msg, ELE_GET_INFO_RSP_MSG_SZ); if (ret < 0) { ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); return ret; } - ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_GET_INFO_REQ, + ret = se_val_rsp_hdr_n_status(priv->priv_dev_ctx, rx_msg, ELE_GET_INFO_REQ, ELE_GET_INFO_RSP_MSG_SZ, priv->if_defs->base_api_ver); if (ret < 0) { @@ -144,12 +145,12 @@ int ele_ping(struct se_if_priv *priv) se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, ELE_PING_REQ, ELE_PING_REQ_SZ, true); - ret = ele_msg_send_rcv(priv, tx_msg, ELE_PING_REQ_SZ, rx_msg, - ELE_PING_RSP_SZ); + ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_PING_REQ_SZ, + rx_msg, ELE_PING_RSP_SZ); if (ret < 0) return ret; - ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_PING_REQ, + ret = se_val_rsp_hdr_n_status(priv->priv_dev_ctx, rx_msg, ELE_PING_REQ, ELE_PING_RSP_SZ, priv->if_defs->base_api_ver); @@ -203,12 +204,12 @@ int ele_service_swap(struct se_if_priv *priv, if (ret) return -EINVAL; - ret = ele_msg_send_rcv(priv, tx_msg, ELE_SERVICE_SWAP_REQ_MSG_SZ, + ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_SERVICE_SWAP_REQ_MSG_SZ, rx_msg, ELE_SERVICE_SWAP_RSP_MSG_SZ); if (ret < 0) return ret; - ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_SERVICE_SWAP_REQ, + ret = se_val_rsp_hdr_n_status(priv->priv_dev_ctx, rx_msg, ELE_SERVICE_SWAP_REQ, ELE_SERVICE_SWAP_RSP_MSG_SZ, priv->if_defs->base_api_ver); if (ret) @@ -260,12 +261,12 @@ int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr, tx_msg->data[1] = 0; tx_msg->data[2] = lower_32_bits(img_addr); - ret = ele_msg_send_rcv(priv, tx_msg, ELE_FW_AUTH_REQ_SZ, rx_msg, + ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_FW_AUTH_REQ_SZ, rx_msg, ELE_FW_AUTH_RSP_MSG_SZ); if (ret < 0) return ret; - ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_FW_AUTH_REQ, + ret = se_val_rsp_hdr_n_status(priv->priv_dev_ctx, rx_msg, ELE_FW_AUTH_REQ, ELE_FW_AUTH_RSP_MSG_SZ, priv->if_defs->base_api_ver); @@ -309,12 +310,12 @@ int ele_debug_dump(struct se_if_priv *priv) do { memset(rx_msg, 0x0, ELE_DEBUG_DUMP_RSP_SZ); - ret = ele_msg_send_rcv(priv, tx_msg, ELE_DEBUG_DUMP_REQ_SZ, + ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_DEBUG_DUMP_REQ_SZ, rx_msg, ELE_DEBUG_DUMP_RSP_SZ); if (ret < 0) return ret; - ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_DEBUG_DUMP_REQ, + ret = se_val_rsp_hdr_n_status(priv->priv_dev_ctx, rx_msg, ELE_DEBUG_DUMP_REQ, ELE_DEBUG_DUMP_RSP_SZ, priv->if_defs->base_api_ver); if (ret) { diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c index c4f87fd0fe5f..838d2f957e74 100644 --- a/drivers/firmware/imx/ele_common.c +++ b/drivers/firmware/imx/ele_common.c @@ -47,7 +47,7 @@ int se_update_msg_chksum(u32 *msg, u32 msg_len) /** * ele_msg_rcv() - wait for a response from the secure enclave. - * @priv: pointer to the SE interface private data. + * @dev_ctx: pointer to the SE dev context data. * @se_clbk_hdl: callback handle whose completion will be signaled when the * response arrives. * @@ -60,8 +60,9 @@ int se_update_msg_chksum(u32 *msg, u32 msg_len) * Return: number of bytes received on success, negative errno on error * (e.g. -ETIMEDOUT, -ERESTARTSYS). */ -int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl) +int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk_hdl) { + struct se_if_priv *priv = dev_ctx->priv; bool is_rsp_wait_with_timeout = false; bool wait_uninterruptible = false; unsigned long remaining_jiffies; @@ -150,7 +151,7 @@ int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl) /** * ele_msg_send() - send a message to the secure enclave over the mailbox. - * @priv: pointer to the SE interface private data. + * @dev_ctx: pointer to the SE device context. * @tx_msg: buffer containing the message to send. * @tx_msg_sz: size of @tx_msg in bytes; must match the size field in the * message header. @@ -161,7 +162,7 @@ int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl) * * Return: @tx_msg_sz on success, negative errno on error. */ -int ele_msg_send(struct se_if_priv *priv, +int ele_msg_send(struct se_if_device_ctx *dev_ctx, void *tx_msg, int tx_msg_sz) { @@ -173,9 +174,9 @@ int ele_msg_send(struct se_if_priv *priv, * carried in the message. */ if (header->size << 2 != tx_msg_sz) { - dev_err(priv->dev, - "User buf hdr: 0x%x, sz mismatched with input-sz (%d != %d).\n", - *(u32 *)header, header->size << 2, tx_msg_sz); + dev_err(dev_ctx->priv->dev, + "%s: User buf hdr: 0x%x, sz mismatched with input-sz (%d != %d).\n", + dev_ctx->devname, *(u32 *)header, header->size << 2, tx_msg_sz); return -EINVAL; } @@ -185,9 +186,10 @@ int ele_msg_send(struct se_if_priv *priv, * caller-provided tx_msg pointer after mbox_send_message() returns, so * the caller-owned buffer may be released after a successful send. */ - err = mbox_send_message(priv->tx_chan, tx_msg); + err = mbox_send_message(dev_ctx->priv->tx_chan, tx_msg); if (err < 0) { - dev_err(priv->dev, "Error: mbox_send_message failure.\n"); + dev_err(dev_ctx->priv->dev, + "%s: Error: mbox_send_message failure.\n", dev_ctx->devname); return err; } @@ -199,6 +201,7 @@ static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + priv->waiting_rsp_clbk_hdl.dev_ctx = NULL; priv->waiting_rsp_clbk_hdl.rx_msg = NULL; priv->waiting_rsp_clbk_hdl.rx_msg_sz = 0; spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); @@ -206,7 +209,7 @@ static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) /** * ele_msg_send_rcv() - send a command and wait for the response. - * @priv: pointer to the SE interface private data. + * @dev_ctx: pointer to the dev_ctx data. * @tx_msg: buffer containing the command message to send. * @tx_msg_sz: size of @tx_msg in bytes. * @rx_msg: caller-provided buffer to receive the response into. @@ -219,32 +222,34 @@ static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) * * Return: number of bytes received on success, negative errno on error. */ -int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz, - void *rx_msg, int exp_rx_msg_sz) +int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg, + int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz) { + struct se_if_priv *priv = dev_ctx->priv; unsigned long flags; int err; guard(mutex)(&priv->se_if_cmd_lock); if (atomic_read(&priv->fw_busy)) { - dev_dbg(priv->dev, "ELE became unresponsive.\n"); + dev_dbg(priv->dev, "%s: ELE became unresponsive.\n", dev_ctx->devname); return -EBUSY; } reinit_completion(&priv->waiting_rsp_clbk_hdl.done); /* Publish rx_msg/rx_msg_sz under the lock read by se_if_rx_callback(). */ spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + priv->waiting_rsp_clbk_hdl.dev_ctx = dev_ctx; priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz; priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg; spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); - err = ele_msg_send(priv, tx_msg, tx_msg_sz); + err = ele_msg_send(dev_ctx, tx_msg, tx_msg_sz); if (err < 0) { ele_msg_send_rcv_cleanup(priv); return err; } - err = ele_msg_rcv(priv, &priv->waiting_rsp_clbk_hdl); + err = ele_msg_rcv(dev_ctx, &priv->waiting_rsp_clbk_hdl); if (priv->waiting_rsp_clbk_hdl.signal_rcvd) { /* @@ -255,7 +260,8 @@ int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz, if (err > 0) err = -ERESTARTSYS; priv->waiting_rsp_clbk_hdl.signal_rcvd = false; - dev_dbg(priv->dev, "Err[0x%x]:Interrupted by signal.\n", err); + dev_dbg(priv->dev, "%s: Err[0x%x]:Interrupted by signal.\n", + dev_ctx->devname, err); } ele_msg_send_rcv_cleanup(priv); @@ -290,6 +296,11 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) { struct se_clbk_handle *se_clbk_hdl; struct device *dev = mbox_cl->dev; + /* + * devname_snap: a local copy of dev_ctx->devname taken while + * clbk_rx_lock is held. + */ + char devname_snap[32]; struct se_msg_hdr *header; bool sz_mismatch = false; struct se_if_priv *priv; @@ -313,7 +324,7 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) if (header->tag == priv->if_defs->cmd_tag) { se_clbk_hdl = &priv->cmd_receiver_clbk_hdl; spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); - if (!se_clbk_hdl->rx_msg) { + if (!se_clbk_hdl->dev_ctx || !se_clbk_hdl->rx_msg) { spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); dev_warn(dev, "No command receiver registered for message: %.8x\n", *((u32 *)header)); @@ -327,8 +338,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) * SE_IOCTL_ENABLE_CMD_RCV and is not subject to the timeout/circuit- * breaker handling used for rsp_tag messages. */ - dev_dbg(dev, "Selecting cmd receiver: for mesg header:0x%x.\n", - *(u32 *)header); + dev_dbg(dev, "Selecting cmd receiver:%s for mesg header:0x%x.\n", + se_clbk_hdl->dev_ctx->devname, *(u32 *)header); /* * Pre-allocated buffer of MAX_NVM_MSG_LEN @@ -343,13 +354,15 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) * Clamp the copy length to the pre-allocated receiver buffer (MAX_NVM_MSG_LEN). */ se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, MAX_NVM_MSG_LEN); + strscpy(devname_snap, se_clbk_hdl->dev_ctx->devname, + sizeof(devname_snap)); memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz); complete(&se_clbk_hdl->done); spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); if (sz_mismatch) dev_err(dev, - "CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n", - *(u32 *)header, + "%s: CMD-RCVER NVM: hdr(0x%x) with different sz(%d != %d).\n", + devname_snap, *(u32 *)header, (header->size << 2), rx_msg_sz); } else if (header->tag == priv->if_defs->rsp_tag) { bool exception_for_sz_mismatch = check_hdr_exception_for_sz(priv, header); @@ -371,8 +384,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) return; } exp_rx_msg_sz = se_clbk_hdl->rx_msg_sz; - dev_dbg(dev, "Selecting resp waiter: for mesg header:0x%x.\n", - *(u32 *)header); + dev_dbg(dev, "Selecting resp waiter:%s for mesg header:0x%x.\n", + se_clbk_hdl->dev_ctx->devname, *(u32 *)header); /* * For rsp_tag traffic, the sender provides the expected response @@ -384,14 +397,17 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) sz_mismatch = true; se_clbk_hdl->rx_msg_sz = min(rx_msg_sz, exp_rx_msg_sz); + /* Snapshot devname before complete() can free the context. */ + strscpy(devname_snap, se_clbk_hdl->dev_ctx->devname, + sizeof(devname_snap)); memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz); complete(&se_clbk_hdl->done); spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); if (sz_mismatch) dev_err(dev, - "Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n", - *(u32 *)header, + "%s: Rsp to CMD: hdr(0x%x) with different sz(%d != %d).\n", + devname_snap, *(u32 *)header, (header->size << 2), exp_rx_msg_sz); } else { dev_err(dev, "Failed to select a device for message: %.8x\n", @@ -401,7 +417,7 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) /** * se_val_rsp_hdr_n_status() - validate a response message header and status. - * @priv: pointer to the SE interface private data. + * @dev_ctx: pointer to the SE device context. * @msg: response message buffer to validate. * @msg_id: expected command identifier. * @sz: expected message size in bytes. @@ -420,9 +436,10 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) * the firmware status indicates a command failure, -ENOSPC if the response * size does not match @sz. */ -int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg, +int se_val_rsp_hdr_n_status(struct se_if_device_ctx *dev_ctx, struct se_api_msg *msg, u8 msg_id, u8 sz, u8 version) { + struct se_if_priv *priv = dev_ctx->priv; struct se_msg_hdr *header = &msg->header; u32 status; diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h index 39bba4ebe8b7..89ae4c335e7b 100644 --- a/drivers/firmware/imx/ele_common.h +++ b/drivers/firmware/imx/ele_common.h @@ -16,16 +16,16 @@ int se_update_msg_chksum(u32 *msg, u32 msg_len); -int ele_msg_rcv(struct se_if_priv *priv, struct se_clbk_handle *se_clbk_hdl); +int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk_hdl); -int ele_msg_send(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz); +int ele_msg_send(struct se_if_device_ctx *dev_ctx, void *tx_msg, int tx_msg_sz); -int ele_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz, - void *rx_msg, int exp_rx_msg_sz); +int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg, + int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz); void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg); -int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg, +int se_val_rsp_hdr_n_status(struct se_if_device_ctx *dev_ctx, struct se_api_msg *msg, u8 msg_id, u8 sz, u8 version); /* Fill a command message header with a given command ID and length in bytes. */ diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c index 0013c960ec43..b5d3421c0987 100644 --- a/drivers/firmware/imx/se_ctrl.c +++ b/drivers/firmware/imx/se_ctrl.c @@ -294,6 +294,29 @@ static int get_se_soc_info(struct se_if_priv *priv, const struct se_soc_info *se return 0; } +static int init_misc_device_context(struct se_if_priv *priv, int ch_id, + struct se_if_device_ctx **new_dev_ctx) +{ + struct se_if_device_ctx *dev_ctx; + + dev_ctx = kzalloc_obj(*dev_ctx); + if (!dev_ctx) + return -ENOMEM; + + dev_ctx->devname = kasprintf(GFP_KERNEL, "%s0_ch%d", + get_se_if_name(priv->if_defs->se_if_type), + ch_id); + if (!dev_ctx->devname) { + kfree(dev_ctx); + return -ENOMEM; + } + + dev_ctx->priv = priv; + *new_dev_ctx = dev_ctx; + + return 0; +} + static int se_if_request_channel(struct device *dev, struct mbox_chan **chan, struct mbox_client *cl, const char *name) { @@ -337,6 +360,12 @@ static void se_if_probe_cleanup(void *plat_dev) of_reserved_mem_device_release(dev); dev_set_drvdata(dev, NULL); + + if (priv->priv_dev_ctx) { + kfree(priv->priv_dev_ctx->devname); + kfree(priv->priv_dev_ctx); + } + mutex_destroy(&priv->load_fw.load_fw_lock); mutex_destroy(&priv->se_if_cmd_lock); kfree(priv); @@ -426,6 +455,11 @@ static int se_if_probe(struct platform_device *pdev) load_fw->imem_mgmt = true; } + ret = init_misc_device_context(priv, 0, &priv->priv_dev_ctx); + if (ret) + return dev_err_probe(dev, ret, + "Failed to create device contexts.\n"); + if (if_node->if_defs.se_if_type == SE_TYPE_ID_HSM) { ret = get_se_soc_info(priv, se_info); if (ret) diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h index 54b2a262a2c3..dd4a1ea7e35a 100644 --- a/drivers/firmware/imx/se_ctrl.h +++ b/drivers/firmware/imx/se_ctrl.h @@ -20,6 +20,7 @@ #define MESSAGING_VERSION_7 0x7 struct se_clbk_handle { + struct se_if_device_ctx *dev_ctx; struct completion done; bool signal_rcvd; u32 rx_msg_sz; @@ -44,6 +45,12 @@ struct se_imem_buf { u32 state; }; +/* Private struct for each char device instance. */ +struct se_if_device_ctx { + struct se_if_priv *priv; + const char *devname; +}; + /* Header of the messages exchange with the EdgeLock Enclave */ struct se_msg_hdr { u8 ver; @@ -106,6 +113,8 @@ struct se_if_priv { struct se_fw_load_info load_fw; atomic_t fw_busy; + + struct se_if_device_ctx *priv_dev_ctx; }; char *get_se_if_name(u8 se_if_id); -- cgit v1.2.3 From 9299b23e2945983d3f0a1d0cc07ffb144ab0eba5 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:10:02 +0530 Subject: firmware: imx: adds miscdev Adds the driver for communication interface to secure-enclave, that enables exchanging messages with NXP secure enclave HW IP(s) like EdgeLock Enclave, from: - User-Space Applications via character driver. ABI documentation for the NXP secure-enclave driver. User-space library using this driver: - i.MX Secure Enclave library: -- URL: https://github.com/nxp-imx/imx-secure-enclave.git, - i.MX Secure Middle-Ware: -- URL: https://github.com/nxp-imx/imx-smw.git Following checks are performed on the incoming msg-header, to block exchanging invalid arbitrary commands: - maximum allowed words, - check if command-tag & response-tag are valid - version, - command id validation check, to allow limited base-line API(s) and restrict following: - exchanging power management commands. - reset requests. - BBSM configuration requests. - re-initializing the FW. - RNG init - CAAM resource release management - SE's internal memory management. from user-space. Signed-off-by: Pankaj Gupta Signed-off-by: Frank Li --- Documentation/ABI/testing/se-cdev | 45 + drivers/firmware/imx/Makefile | 2 +- drivers/firmware/imx/ele_base_msg.c | 113 +- drivers/firmware/imx/ele_base_msg.h | 19 + drivers/firmware/imx/ele_common.c | 456 ++++++- drivers/firmware/imx/ele_common.h | 104 +- drivers/firmware/imx/ele_fw_api.c | 406 ++++++ drivers/firmware/imx/ele_fw_api.h | 104 ++ drivers/firmware/imx/ele_msg_addr_field.c | 619 +++++++++ drivers/firmware/imx/se_ctrl.c | 1929 ++++++++++++++++++++++++++++- drivers/firmware/imx/se_ctrl.h | 190 ++- include/uapi/linux/se_ioctl.h | 97 ++ 12 files changed, 4000 insertions(+), 84 deletions(-) create mode 100644 Documentation/ABI/testing/se-cdev create mode 100644 drivers/firmware/imx/ele_fw_api.c create mode 100644 drivers/firmware/imx/ele_fw_api.h create mode 100644 drivers/firmware/imx/ele_msg_addr_field.c create mode 100644 include/uapi/linux/se_ioctl.h diff --git a/Documentation/ABI/testing/se-cdev b/Documentation/ABI/testing/se-cdev new file mode 100644 index 000000000000..0a353caeaab2 --- /dev/null +++ b/Documentation/ABI/testing/se-cdev @@ -0,0 +1,45 @@ +What: /dev/_mu[0-9]+_ch[0-9]+ +Date: Mar 2025 +KernelVersion: 6.8 +Contact: linux-imx@nxp.com, pankaj.gupta@nxp.com +Description: + NXP offers multiple hardware IP(s) for secure enclaves like EdgeLock- + Enclave(ELE), SECO. The character device file descriptors + /dev/_mu*_ch* are the interface between userspace NXP's secure- + enclave shared library and the kernel driver. + + The ioctl(2)-based ABI is defined and documented in + [include] + ioctl(s) are used primarily for: + + - shared memory management + - allocation of I/O buffers + - getting mu info + - setting a dev-ctx as receiver to receive all the commands from FW + - getting SoC info + - send command and receive command response + + The following file operations are supported: + + open(2) + Currently the only useful flags are O_RDWR. + + read(2) + Every read() from the opened character device context is waiting on + wait_for_completion_interruptible_timeout, that gets set by the + registered mailbox callback function, indicating a message received + from the firmware on message-unit. + + write(2) + Every write() to the opened character device context needs to acquire + `fops_lock` + `se_if_cmd_lock` lock before sending message on to the + message unit. + + close(2) + Stops and frees up the I/O contexts that were associated + with the file descriptor. + +Users: https://github.com/nxp-imx/imx-secure-enclave.git, + https://github.com/nxp-imx/imx-smw.git, + crypto/skcipher, + drivers/nvmem/imx-ocotp-ele.c diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile index 4412b15846b1..33f30eaedad5 100644 --- a/drivers/firmware/imx/Makefile +++ b/drivers/firmware/imx/Makefile @@ -4,5 +4,5 @@ obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o obj-${CONFIG_IMX_SCMI_CPU_DRV} += sm-cpu.o obj-${CONFIG_IMX_SCMI_MISC_DRV} += sm-misc.o obj-${CONFIG_IMX_SCMI_LMM_DRV} += sm-lmm.o -sec_enclave-objs = se_ctrl.o ele_common.o ele_base_msg.o +sec_enclave-objs = se_ctrl.o ele_common.o ele_base_msg.o ele_fw_api.o ele_msg_addr_field.o obj-${CONFIG_IMX_SEC_ENCLAVE} += sec_enclave.o diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c index 650153d39f46..b60665120db2 100644 --- a/drivers/firmware/imx/ele_base_msg.c +++ b/drivers/firmware/imx/ele_base_msg.c @@ -15,13 +15,66 @@ #define FW_DBG_DUMP_FIXED_STR "ELE" -static void ele_get_info_cleanup(struct se_if_priv *priv, u32 *buf, dma_addr_t d_addr, - size_t size) +int ele_uapi_allowed_base_cmd(struct se_if_device_ctx *dev_ctx, + struct se_msg_hdr *header, u32 tx_msg_sz) { - if (priv->mem_pool) - gen_pool_free(priv->mem_pool, (unsigned long)buf, size); - else - dma_free_coherent(priv->dev, size, buf, d_addr); + struct se_api_msg *msg = container_of(header, struct se_api_msg, header); + const struct se_cmd_addr_field *fields; + size_t count; + + /* + * Identify the command first. Only commands in this allow-list may be + * issued from userspace; everything else is rejected. Once a command is + * known to be supported, decide whether it needs a DMA-address boundary + * check and, if so, run it before returning. + */ + switch (header->command) { + case ELE_PING_REQ: + case ELE_DEBUG_DUMP_REQ: + case ELE_OEM_VERIFY_IMAGE_REQ: + case ELE_OEM_REL_CONTAINER_REQ: + case ELE_FW_LIFE_CYCLE_REQ: + case ELE_READ_FUSE_REQ: + case ELE_GET_FW_VERS_REQ: + case ELE_RETURN_LIFE_CYCLE_REQ: + case ELE_GET_EVENT_REQ: + case ELE_COMMIT_REQ: + case ELE_GET_FW_STATUS_REQ: + case ELE_WRITE_FUSE: + case ELE_WRITE_SHADOW_FUSE_REQ: + case ELE_READ_SHADOW_FUSE_REQ: + return 0; + default: + /* Base commands that embed DMA addresses. */ + fields = ele_base_cmd_addr_fields(header->command, &count); + if (!count) + return -EOPNOTSUPP; + return se_val_cmd_addrs(dev_ctx, msg, tx_msg_sz, fields, count); + } +} + +static void ele_get_info_cleanup(struct se_if_priv *priv) +{ + /* For the case when priv->mem_pool != NULL: + * + * If this probe-time transaction timed out, the firmware may + * still write into the SRAM buffer after this function returns. + * Do not release it back to the pool while the firmware-busy + * circuit breaker still marks this context as owning an + * outstanding transaction. The buffer is reclaimed with the + * device on unbind; leaking this fixed-size probe buffer is + * preferable to letting the firmware corrupt reused pool memory. + * This mirrors the guard already applied on the shared-memory + * cleanup path below. + */ + + if (priv->mem_pool) { + if (se_is_fw_busy_ctx(priv->priv_dev_ctx)) + return; + se_cleanup_mem_pool_buf(priv->priv_dev_ctx, true); + } else { + se_dev_ctx_shared_mem_cleanup(priv->priv_dev_ctx); + } } /** @@ -45,6 +98,7 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) if (!priv) return -EINVAL; + guard(mutex)(&priv->priv_dev_ctx->fops_lock); memset(s_info, 0x0, sizeof(*s_info)); struct se_api_msg *tx_msg __free(kfree) = @@ -58,24 +112,23 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) return -ENOMEM; get_info_len = ELE_GET_INFO_BUFF_SZ; - if (priv->mem_pool) - get_info_data = gen_pool_dma_alloc(priv->mem_pool, - get_info_len, - &get_info_addr); - else - get_info_data = dma_alloc_coherent(priv->dev, - get_info_len, - &get_info_addr, - GFP_KERNEL); - if (!get_info_data) { - dev_err(priv->dev, - "%s: Failed to allocate get_info_addr.\n", __func__); - return -ENOMEM; + if (priv->mem_pool) { + ret = se_get_mem_pool_buf(priv->priv_dev_ctx, &get_info_data, + &get_info_addr, get_info_len); + if (ret) { + dev_err(priv->dev, "Failed[0x%x] to alloc from gen_pool.\n", ret); + return -ENOMEM; + } + } else { + ret = get_shared_mem_slot(priv->priv_dev_ctx, + &get_info_len, &get_info_addr, + &get_info_data); + if (ret) { + dev_err(priv->dev, "Failed to allocate buffer.\n"); + return -ENOMEM; + } } - /* gen_pool_dma_alloc() does not zero the buffer. */ - memset(get_info_data, 0, get_info_len); - se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, ELE_GET_INFO_REQ, ELE_GET_INFO_REQ_MSG_SZ, true); @@ -84,9 +137,9 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) tx_msg->data[2] = sizeof(*s_info); ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_GET_INFO_REQ_MSG_SZ, - rx_msg, ELE_GET_INFO_RSP_MSG_SZ); + rx_msg, ELE_GET_INFO_RSP_MSG_SZ, NULL); if (ret < 0) { - ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); + ele_get_info_cleanup(priv); return ret; } @@ -94,13 +147,13 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info) ELE_GET_INFO_RSP_MSG_SZ, priv->if_defs->base_api_ver); if (ret < 0) { - ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); + ele_get_info_cleanup(priv); return ret; } memcpy(s_info, get_info_data, sizeof(*s_info)); - ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len); + ele_get_info_cleanup(priv); return ret; } @@ -146,7 +199,7 @@ int ele_ping(struct se_if_priv *priv) ELE_PING_REQ, ELE_PING_REQ_SZ, true); ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_PING_REQ_SZ, - rx_msg, ELE_PING_RSP_SZ); + rx_msg, ELE_PING_RSP_SZ, NULL); if (ret < 0) return ret; @@ -205,7 +258,7 @@ int ele_service_swap(struct se_if_priv *priv, return -EINVAL; ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_SERVICE_SWAP_REQ_MSG_SZ, - rx_msg, ELE_SERVICE_SWAP_RSP_MSG_SZ); + rx_msg, ELE_SERVICE_SWAP_RSP_MSG_SZ, NULL); if (ret < 0) return ret; @@ -262,7 +315,7 @@ int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr, tx_msg->data[2] = lower_32_bits(img_addr); ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_FW_AUTH_REQ_SZ, rx_msg, - ELE_FW_AUTH_RSP_MSG_SZ); + ELE_FW_AUTH_RSP_MSG_SZ, NULL); if (ret < 0) return ret; @@ -311,7 +364,7 @@ int ele_debug_dump(struct se_if_priv *priv) memset(rx_msg, 0x0, ELE_DEBUG_DUMP_RSP_SZ); ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_DEBUG_DUMP_REQ_SZ, - rx_msg, ELE_DEBUG_DUMP_RSP_SZ); + rx_msg, ELE_DEBUG_DUMP_RSP_SZ, NULL); if (ret < 0) return ret; diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h index 02525d5e2873..50e2a1a75716 100644 --- a/drivers/firmware/imx/ele_base_msg.h +++ b/drivers/firmware/imx/ele_base_msg.h @@ -29,6 +29,19 @@ #define ELE_DEBUG_DUMP_REQ_SZ 0x4 #define ELE_DEBUG_DUMP_RSP_SZ 0x5c +#define ELE_OEM_AUTH_CONTAINER_REQ 0x87 +#define ELE_OEM_VERIFY_IMAGE_REQ 0x88 +#define ELE_OEM_REL_CONTAINER_REQ 0x89 +#define ELE_FW_LIFE_CYCLE_REQ 0x95 +#define ELE_READ_FUSE_REQ 0x97 +#define ELE_GET_FW_VERS_REQ 0x9d +#define ELE_RETURN_LIFE_CYCLE_REQ 0xa0 +#define ELE_GET_EVENT_REQ 0xa2 +#define ELE_COMMIT_REQ 0xa8 +#define ELE_GEN_KEY_BLOB_REQ 0xaf +#define ELE_GET_FW_STATUS_REQ 0xc5 +#define ELE_WRITE_FUSE 0xd6 + #define ELE_GET_INFO_REQ 0xda #define ELE_GET_INFO_REQ_MSG_SZ 0x10 #define ELE_GET_INFO_RSP_MSG_SZ 0x08 @@ -71,6 +84,10 @@ struct ele_dev_info { #define ELE_GET_INFO_BUFF_SZ (sizeof(struct ele_dev_info) \ + ELE_DEV_INFO_EXTRA_SZ) +#define ELE_DEV_ATTEST_REQ 0xdb +#define ELE_WRITE_SHADOW_FUSE_REQ 0xf2 +#define ELE_READ_SHADOW_FUSE_REQ 0xf3 + #define ELE_SERVICE_SWAP_REQ 0xdf #define ELE_SERVICE_SWAP_REQ_MSG_SZ 0x18 #define ELE_SERVICE_SWAP_RSP_MSG_SZ 0x0c @@ -97,4 +114,6 @@ int ele_service_swap(struct se_if_priv *priv, dma_addr_t addr, int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr, dma_addr_t img_addr); int ele_debug_dump(struct se_if_priv *priv); +int ele_uapi_allowed_base_cmd(struct se_if_device_ctx *dev_ctx, + struct se_msg_hdr *header, u32 tx_msg_sz); #endif diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c index 838d2f957e74..3a0cd62f2ba5 100644 --- a/drivers/firmware/imx/ele_common.c +++ b/drivers/firmware/imx/ele_common.c @@ -5,6 +5,217 @@ #include "ele_base_msg.h" #include "ele_common.h" +#include "ele_fw_api.h" +#include "se_ctrl.h" + +int se_chk_tx_rsp_msg_hdr(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz) +{ + struct se_if_priv *priv = dev_ctx->priv; + + if (!header->size || header->size > MAX_WORD_SIZE) + return -EINVAL; + + if (header->tag != priv->if_defs->rsp_tag) + return -EINVAL; + + if (header->ver == priv->if_defs->base_api_ver) + return -EINVAL; + + else if (header->ver == priv->if_defs->fw_api_ver) + return ele_uapi_allowed_fw_rsp(dev_ctx, header, tx_msg_sz); + + return -EINVAL; +} + +int se_chk_tx_cmd_msg_hdr(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz, u32 rx_msg_sz) +{ + struct se_if_priv *priv = dev_ctx->priv; + + if (!header->size || header->size > MAX_WORD_SIZE) + return -EINVAL; + + if (header->tag != priv->if_defs->cmd_tag) + return -EINVAL; + + if (header->ver == priv->if_defs->base_api_ver) + return ele_uapi_allowed_base_cmd(dev_ctx, header, tx_msg_sz); + else if (header->ver == priv->if_defs->fw_api_ver) + return ele_uapi_allowed_fw_cmd(dev_ctx, header, tx_msg_sz, rx_msg_sz); + + return -EINVAL; +} + +/* + * Reject a command that embeds a DMA physical address which does not point + * inside this context's shared-memory window. The userspace library stages all + * command buffers in that coherent region (see get_shared_mem_slot), so any + * address outside [dma_addr, dma_addr + size) is not one the driver handed out + * and must not be forwarded to firmware. Absent optional buffers are encoded as + * a zero address and skipped; polymorphic key words are only range-checked when + * their gating flag marks them as a plaintext-key buffer rather than an integer + * key identifier. An address may occupy one word (FW-API, low 32 bits only) or + * two words (some base-API commands split it into low and high halves). + * + * When a field also names a size word, the buffer length carried there is + * validated too: the whole buffer [addr, addr + len) must fit inside the + * window, not just its start address. The check is written as len > end - addr + * (addr is already known to be < end) so it cannot overflow. + */ +int se_val_cmd_addrs(struct se_if_device_ctx *dev_ctx, struct se_api_msg *msg, + u32 tx_msg_sz, const struct se_cmd_addr_field *fields, + size_t count) +{ + const struct se_shared_mem *mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem; + u32 payload_words; + size_t i; + u64 base, end; + + if (!fields || !count) + return 0; + + if (!msg) + return -EINVAL; + + /* Number of complete u32 payload words present after the header. */ + if (tx_msg_sz < SE_MU_HDR_SZ) + return -EINVAL; + /* + * The caller-supplied byte count must agree with the size the firmware + * will act on (header word-size field, in 32-bit words), so a lying + * header cannot make us validate fewer words than are actually sent. + */ + if (tx_msg_sz != (u32)msg->header.size * sizeof(u32)) + return -EINVAL; + payload_words = (tx_msg_sz - SE_MU_HDR_SZ) / sizeof(u32); + + base = (u64)mem->dma_addr; + end = base + mem->size; + + /* A zero-sized or wrapping window can never contain a valid buffer. */ + if (end <= base) + return -EINVAL; + + for (i = 0; i < count; i++) { + const struct se_cmd_addr_field *f = &fields[i]; + u64 addr; + + /* Every word the field references must lie within the message. */ + if (f->lsb_idx >= payload_words) + return -EINVAL; + if (f->has_msb && f->msb_idx >= payload_words) + return -EINVAL; + + if (f->flag_idx != SE_CMD_ADDR_ALWAYS) { + bool flag_set; + + if (f->flag_idx >= payload_words) + return -EINVAL; + + flag_set = !!(msg->data[f->flag_idx] & f->flag_mask); + /* + * When the flag does not select DMA-address mode the + * word holds an integer key identifier; leave it alone. + */ + if (flag_set != f->is_addr_when_set) + continue; + } + + addr = msg->data[f->lsb_idx]; + if (f->has_msb) + addr |= (u64)msg->data[f->msb_idx] << 32; + + /* Zero marks an absent optional buffer. */ + if (!addr) + continue; + + if (addr < base || addr >= end) + return -EACCES; + + /* + * The whole buffer [addr, addr + len) must fit inside the + * window, not just its start. addr is already >= base and + * < end here, so end - addr is a positive value and every + * "len > end - addr" comparison below cannot overflow. Where + * the length comes from depends on f->size_idx. + */ + switch (f->size_idx) { + case SE_CMD_ADDR_DEDUCE_SZ: { + /* + * No length word is carried in the payload. Instead the + * buffer begins with a struct fw_tag_len_vers_info + * header whose length field gives the total buffer byte + * count. + */ + const struct fw_tag_len_vers_info *hdr; + u64 len; + + /* + * The header itself must lie inside the window before it + * can be read. addr is already >= base and < end, so + * end - addr is positive and cannot overflow. + */ + if (sizeof(*hdr) > end - addr) + return -EACCES; + + /* + * Translate the validated DMA address to its kernel + * virtual alias inside the coherent shared-memory + * mapping before dereferencing it; a raw DMA address + * must never be dereferenced directly. + */ + hdr = (const struct fw_tag_len_vers_info *) + (mem->ptr + (addr - base)); + len = le16_to_cpu(hdr->length); + if (!len || len > end - addr) + return -EACCES; + break; + } + case SE_CMD_ADDR_FIXED_SIZE: + /* buf_size: literal byte count (FW-defined constant). */ + if (!f->buf_size) + return -EINVAL; + if ((u64)f->buf_size > end - addr) + return -EACCES; + break; + case SE_CMD_RCVR_ADDR_VAR_SIZE: { + struct cmd_rcvr_data_info *crcvr_info = + &dev_ctx->priv->crcvr_info; + /* + * Export-response buffer: the size was supplied by FW + * in the preceding export command and stored per SE + * interface in cmd_rcvr_var_size. + */ + if ((u64)crcvr_info->cmd_rcvr_var_size > end - addr) + return -EACCES; + break; + } + default: { + /* size_idx names a payload word carrying the length. */ + u64 len; + + if (f->size_idx >= payload_words) + return -EINVAL; + + /* size_mask == 0 with a valid size_idx is a descriptor bug. */ + if (!f->size_mask) + return -EINVAL; + + /* + * Widen to u64 before shifting: size_shift is u8 and + * shifting a u32 by >= 32 is undefined behaviour. + */ + len = ((u64)msg->data[f->size_idx] >> f->size_shift) & f->size_mask; + if (len > end - addr) + return -EACCES; + break; + } + } + } + + return 0; +} /** * se_update_msg_chksum() - calculate and update message checksum word. @@ -45,6 +256,39 @@ int se_update_msg_chksum(u32 *msg, u32 msg_len) return 0; } +static void se_mark_fw_busy(struct se_if_device_ctx *dev_ctx) +{ + struct se_if_priv *priv = dev_ctx->priv; + struct fw_busy_info *fbusy_info = &priv->fw_busy_info; + unsigned long flags; + + spin_lock_irqsave(&fbusy_info->fw_busy_lock, flags); + if (!fbusy_info->fw_busy_dev_ctx) { + kref_get(&dev_ctx->refcount); + fbusy_info->fw_busy_dev_ctx = dev_ctx; + /* + * Snapshot the devname now, while it is still valid. If the + * userspace fd is closed while the breaker is armed, + * cleanup_dev_ctx() frees dev_ctx->devname and sets it to NULL, + * so se_clear_fw_busy() cannot rely on it for its late-response + * diagnostics. devname is short ("%s0_ch%d"); strscpy() safely + * truncates into the fixed buffer. + */ + if (dev_ctx->devname) + strscpy(fbusy_info->devname, dev_ctx->devname, + sizeof(fbusy_info->devname)); + else + fbusy_info->devname[0] = '\0'; + atomic_set(&fbusy_info->fw_busy, 1); + } + spin_unlock_irqrestore(&fbusy_info->fw_busy_lock, flags); +} + +void set_se_rcv_msg_timeout(struct se_if_device_ctx *dev_ctx, u32 timeout_ms) +{ + dev_ctx->rcv_msg_timeout_jiffies = msecs_to_jiffies(timeout_ms); +} + /** * ele_msg_rcv() - wait for a response from the secure enclave. * @dev_ctx: pointer to the SE dev context data. @@ -65,15 +309,26 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk struct se_if_priv *priv = dev_ctx->priv; bool is_rsp_wait_with_timeout = false; bool wait_uninterruptible = false; + bool wait_killable = false; unsigned long remaining_jiffies; unsigned long deadline_jiffies; unsigned long flags; int ret; - remaining_jiffies = msecs_to_jiffies(SE_RCV_MSG_DEFAULT_TIMEOUT_MS); + remaining_jiffies = dev_ctx->rcv_msg_timeout_jiffies; if (se_clbk_hdl == &priv->waiting_rsp_clbk_hdl) { is_rsp_wait_with_timeout = true; deadline_jiffies = jiffies + remaining_jiffies; + + /* + * Internal kernel transactions run on priv_dev_ctx (probe + * get_info/ping, FW auth, PM IMEM swap). They are not tied to a + * restartable syscall, so wait uninterruptibly: PM freezer fake + * signals must not abort them with -ERESTARTSYS. Userspace + * waiters stay interruptible via the deferred-signal path below. + */ + if (se_clbk_hdl->dev_ctx == priv->priv_dev_ctx) + wait_uninterruptible = true; } do { @@ -84,8 +339,14 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk /* Deadline hit: fence hung FW, like the ret==0 path. */ spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); se_clbk_hdl->rx_msg = NULL; - if (!completion_done(&se_clbk_hdl->done)) - atomic_set(&priv->fw_busy, 1); + /* rx_delivered is set only after a real response has + * been copied under clbk_rx_lock, so it correctly + * distinguishes a genuine timeout (no response → mark + * busy) from a spurious teardown-forced wakeup where + * the data is not yet safe to free. + */ + if (!se_clbk_hdl->rx_delivered) + se_mark_fw_busy(dev_ctx); spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); ret = -ETIMEDOUT; break; @@ -96,23 +357,57 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk if (wait_uninterruptible) ret = wait_for_completion_timeout(&se_clbk_hdl->done, remaining_jiffies); + else if (wait_killable) + ret = wait_for_completion_killable_timeout(&se_clbk_hdl->done, + remaining_jiffies); else ret = wait_for_completion_interruptible_timeout(&se_clbk_hdl->done, remaining_jiffies); if (ret == -ERESTARTSYS) { /* - * Record that a signal was observed, then continue waiting non- - * interruptibly until the response arrives or the timeout - * expires. The caller can surface the interruption to userspace - * after the protocol transaction is brought back to a - * synchronized state. + * First, non-fatal signal on the interruptible userspace + * path: defer it. Record that a signal was observed and keep + * waiting - now only killably - until the response arrives or + * the timeout expires. ele_msg_send_rcv() then surfaces the + * interruption to userspace as -ERESTARTSYS once the protocol + * transaction has resynchronised, so the in-flight command is + * neither abandoned nor re-sent. + * + * Waiting killably rather than fully uninterruptibly is what + * keeps a fatal signal (SIGKILL) able to terminate the task: + * a non-fatal signal no longer aborts the wait, but the task + * can never get stuck for the multi-thousand-second long + * timeout and trip the hung-task watchdog. */ - if (is_rsp_wait_with_timeout && + if (is_rsp_wait_with_timeout && !wait_killable && READ_ONCE(se_clbk_hdl->rx_msg)) { WRITE_ONCE(se_clbk_hdl->signal_rcvd, true); - wait_uninterruptible = true; + wait_killable = true; continue; } + + /* + * Command-receiver path, or a fatal signal on the + * killable path: the task is dying but the enclave may + * still DMA into the soon-to-be-freed buffer. Under + * clbk_rx_lock, drop rx_msg and arm fw_busy so a late + * callback cannot write freed memory. Exception: if + * rx_delivered is set a real response already landed, so + * report its size and keep the handle. + */ + if (is_rsp_wait_with_timeout) { + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + if (se_clbk_hdl->rx_delivered) { + ret = se_clbk_hdl->rx_msg_sz; + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + break; + } + if (se_clbk_hdl->rx_msg) { + se_clbk_hdl->rx_msg = NULL; + se_mark_fw_busy(dev_ctx); + } + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + } break; } @@ -132,8 +427,15 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); se_clbk_hdl->rx_msg = NULL; - if (!completion_done(&se_clbk_hdl->done)) - atomic_set(&priv->fw_busy, 1); + /* + * rx_delivered helps to decide if the circuit breaker is armed + * or not. rx_delivered is set only after a real response has + * been copied under clbk_rx_lock, so it correctly distinguishes + * a genuine timeout (no response → mark busy) from a spurious + * teardown-forced wakeup where the data is not yet safe to free. + */ + if (!se_clbk_hdl->rx_delivered) + se_mark_fw_busy(dev_ctx); spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); ret = -ETIMEDOUT; @@ -142,8 +444,35 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk get_se_if_name(priv->if_defs->se_if_type)); break; } + + /* + * A positive wait return normally means a real response. During + * teardown, se_if_probe_cleanup() forces this wait to return via + * complete_all() with no response, while the enclave may still + * DMA into the shared buffer. Treat that as a failed transaction + * and arm the circuit breaker so the buffer is quarantined, not + * freed. + * + * rx_delivered tells the two apart: se_if_rx_callback() sets it + * under clbk_rx_lock only after copying a real response. This + * keeps teardown-time session/storage close responses from being + * mistaken for the forced abort, which would fail the close and + * leak its DMA buffer. + */ + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + if (is_rsp_wait_with_timeout && atomic_read(&priv->going_away) && + !se_clbk_hdl->rx_delivered) { + se_clbk_hdl->rx_msg = NULL; + se_mark_fw_busy(dev_ctx); + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + ret = -ENODEV; + break; + } + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + ret = se_clbk_hdl->rx_msg_sz; break; + } while (ret < 0); return ret; @@ -196,13 +525,15 @@ int ele_msg_send(struct se_if_device_ctx *dev_ctx, return tx_msg_sz; } -static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) +static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv, int *act_rx_msg_sz) { unsigned long flags; spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); priv->waiting_rsp_clbk_hdl.dev_ctx = NULL; priv->waiting_rsp_clbk_hdl.rx_msg = NULL; + if (act_rx_msg_sz) + *act_rx_msg_sz = priv->waiting_rsp_clbk_hdl.rx_msg_sz; priv->waiting_rsp_clbk_hdl.rx_msg_sz = 0; spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); } @@ -214,6 +545,10 @@ static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) * @tx_msg_sz: size of @tx_msg in bytes. * @rx_msg: caller-provided buffer to receive the response into. * @exp_rx_msg_sz: expected response size in bytes. + * @act_rx_msg_sz: optional output pointer; if non-NULL, receives the actual + * number of bytes copied into @rx_msg (min of FW-declared + * size and @exp_rx_msg_sz). Pass NULL when the caller does not + * need this value. * * Holds the SE command lock for the duration of the exchange to prevent * concurrent transactions. Signals are deferred until the protocol @@ -223,29 +558,63 @@ static void ele_msg_send_rcv_cleanup(struct se_if_priv *priv) * Return: number of bytes received on success, negative errno on error. */ int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg, - int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz) + int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz, int *act_rx_msg_sz) { struct se_if_priv *priv = dev_ctx->priv; + struct fw_busy_info *fbusy_info = &priv->fw_busy_info; + struct task_struct *msg_excl_owner; unsigned long flags; int err; guard(mutex)(&priv->se_if_cmd_lock); - if (atomic_read(&priv->fw_busy)) { - dev_dbg(priv->dev, "%s: ELE became unresponsive.\n", dev_ctx->devname); + /* + * Arm under clbk_rx_lock so the going_away check and arming are atomic + * against teardown (closes the lost-wakeup window); priv_dev_ctx close + * commands still pass. Check going_away before fw_busy so a caller + * racing unbind gets the permanent -ENODEV, not the retryable -EBUSY - + * these are deliberately distinct from the transient msg_if reservation. + */ + + spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + msg_excl_owner = READ_ONCE(priv->msg_excl_flow.msg_excl_owner); + if (atomic_read(&priv->going_away) && msg_excl_owner != current) { + spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + return -ENODEV; + } + /* + * fw_busy is the circuit breaker: while it is set, reject new + * transactions with -EBUSY. The one exception is a flow that has + * reserved this interface exclusively for itself via se_reserve_msg_if() + * by publishing its task in priv->msg_excl_flow.msg_excl_owner (e.g. + * the recovery flow in se_clear_fw_busy()). Only that owning task is let + * through here to issue its teardown-close messages; every other caller + * still gets -EBUSY. When the flow calls se_release_msg_if() the owner + * is cleared and the interface returns to general se_if_cmd_lock message + * exchange. The owner is only compared against current, so a stale read + * is harmless (a non-owner can never match) and no msg_excl_lock is + * needed here; there is no deadlock. + */ + if (atomic_read(&fbusy_info->fw_busy) && msg_excl_owner != current) { + spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); return -EBUSY; } + reinit_completion(&priv->waiting_rsp_clbk_hdl.done); - /* Publish rx_msg/rx_msg_sz under the lock read by se_if_rx_callback(). */ - spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); priv->waiting_rsp_clbk_hdl.dev_ctx = dev_ctx; priv->waiting_rsp_clbk_hdl.rx_msg_sz = exp_rx_msg_sz; priv->waiting_rsp_clbk_hdl.rx_msg = rx_msg; + /* + * Arm a fresh transaction: clear the delivered flag so a stale value + * from a previous response cannot make ele_msg_rcv() mistake a + * teardown-forced complete_all() for a genuine firmware response. + */ + priv->waiting_rsp_clbk_hdl.rx_delivered = false; spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); err = ele_msg_send(dev_ctx, tx_msg, tx_msg_sz); if (err < 0) { - ele_msg_send_rcv_cleanup(priv); + ele_msg_send_rcv_cleanup(priv, NULL); return err; } @@ -264,7 +633,7 @@ int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg, dev_ctx->devname, err); } - ele_msg_send_rcv_cleanup(priv); + ele_msg_send_rcv_cleanup(priv, act_rx_msg_sz); return err; } @@ -296,14 +665,15 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) { struct se_clbk_handle *se_clbk_hdl; struct device *dev = mbox_cl->dev; + struct fw_busy_info *fbusy_info; + struct se_msg_hdr *header; + bool sz_mismatch = false; + struct se_if_priv *priv; /* * devname_snap: a local copy of dev_ctx->devname taken while * clbk_rx_lock is held. */ char devname_snap[32]; - struct se_msg_hdr *header; - bool sz_mismatch = false; - struct se_if_priv *priv; unsigned long flags; u32 rx_msg_sz; @@ -311,6 +681,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) if (!priv) return; + fbusy_info = &priv->fw_busy_info; + /* The function can be called with NULL msg */ if (IS_ERR_OR_NULL(msg)) { dev_err(dev, "Message is invalid\n"); @@ -377,9 +749,37 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) se_clbk_hdl = &priv->waiting_rsp_clbk_hdl; spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); if (!se_clbk_hdl->rx_msg) { - /* Close circuit breaker on spinlock race */ - atomic_set(&priv->fw_busy, 0); + /* + * Schedule fw_busy_work only while going_away is clear: + * teardown sets going_away under this lock before + * cancel_work_sync(), so scheduling after that would + * re-queue against freed priv (UAF). schedule_work() + * only enqueues (the handler runs later in process + * context, so se_clear_fw_busy()'s mutex is not taken + * under this spinlock). se_clear_fw_busy() also runs + * from teardown; both take fw_busy_lock first, so the + * second caller sees NULL and returns. + */ + if (atomic_read(&fbusy_info->fw_busy)) { + /* + * Snapshot the late response before scheduling + * fw_busy_work. se_clear_fw_busy() will parse + * this buffer to detect a session-open or + * storage-open response and immediately close + * the leaked firmware handle via + * fw_api_specific_ops(). The buffer is sized + * to MAX_ALLOWED_RX_MSG_SZ; clamp the copy + * length so an oversized FW message cannot + * overflow it. + */ + memcpy(fbusy_info->orphan_fw_rx_msg, msg, + min(rx_msg_sz, + (u32)MAX_ALLOWED_RX_MSG_SZ)); + if (!atomic_read(&priv->going_away)) + schedule_work(&fbusy_info->fw_busy_work); + } spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + dev_info(dev, "ELE responded (late), recovery FW available.\n"); return; } @@ -401,6 +801,12 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg) strscpy(devname_snap, se_clbk_hdl->dev_ctx->devname, sizeof(devname_snap)); memcpy(se_clbk_hdl->rx_msg, msg, se_clbk_hdl->rx_msg_sz); + /* + * Mark that a genuine firmware response was delivered. ele_msg_rcv() + * reads this under clbk_rx_lock to avoid mistaking this response for + * a teardown-forced complete_all() wakeup. + */ + se_clbk_hdl->rx_delivered = true; complete(&se_clbk_hdl->done); spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h index 89ae4c335e7b..332b35eb7db2 100644 --- a/drivers/firmware/imx/ele_common.h +++ b/drivers/firmware/imx/ele_common.h @@ -9,11 +9,15 @@ #include "se_ctrl.h" #define SE_RCV_MSG_DEFAULT_TIMEOUT_MS 3000 +#define SE_RCV_MSG_LONG_TIMEOUT_MS 5000000 #define ELE_SUCCESS_IND 0xD6 #define IMX_ELE_FW_DIR "imx/ele/" +#define MAX_WORD_SIZE 0x20 + +void set_se_rcv_msg_timeout(struct se_if_device_ctx *dev_ctx, u32 val); int se_update_msg_chksum(u32 *msg, u32 msg_len); int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk_hdl); @@ -21,13 +25,106 @@ int ele_msg_rcv(struct se_if_device_ctx *dev_ctx, struct se_clbk_handle *se_clbk int ele_msg_send(struct se_if_device_ctx *dev_ctx, void *tx_msg, int tx_msg_sz); int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg, - int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz); + int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz, + int *act_rx_msg_sz); void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg); int se_val_rsp_hdr_n_status(struct se_if_device_ctx *dev_ctx, struct se_api_msg *msg, u8 msg_id, u8 sz, u8 version); +/* + * Header that prefixes the input buffer of commands whose descriptor uses + * SE_CMD_ADDR_DEDUCE_SZ (e.g. ELE_OEM_AUTH_CONTAINER_REQ, + * ELE_KEYSTORE_REPROV_ENABLE_REQ). The command payload carries only the start + * address of that buffer, but its first four bytes follow this fixed layout: + * the 16-bit length field gives the total byte count of the buffer, so + * se_val_cmd_addrs() can bound-check the whole buffer, not just its start. The + * length is little-endian on the wire; read it with le16_to_cpu(). + */ +struct fw_tag_len_vers_info { + u8 version; + __le16 length; + u8 tag; +} __packed; + +/** + * struct se_cmd_addr_field - One DMA address embedded in an ELE command + * message payload. + * + * A number of ELE commands carry DMA physical addresses inside their message + * payload. se_val_cmd_addrs() range-checks each such address against the + * calling context's shared-memory window before the message reaches firmware. + * + * data[] index = message WORD index - 1, because the 4-byte se_msg_hdr is + * message WORD 0 and se_api_msg.data[0] is message WORD 1. + * + * @lsb_idx: data[] index of the low 32 bits of the address. + * @msb_idx: data[] index of the high 32 bits; valid only when @has_msb is + * set. Some base-API commands split the address into two words; + * FW-API commands do not. + * @has_msb: true when the address occupies two words (@lsb_idx + @msb_idx). + * @flag_idx: data[] index of the flag word that selects whether + * data[@lsb_idx] is a DMA address or an integer key identifier; + * %SE_CMD_ADDR_ALWAYS when the word is always a DMA address. + * @flag_mask: the selecting flag bit, already shifted to its position inside + * the 32-bit little-endian flag word. + * @is_addr_when_set: true when the word is a DMA address if the flag bit is + * set; false when it is an address if the bit is clear + * (inverse polarity, e.g. VERIFY_SIGN OPAQUE_KEY). + * @size_idx: data[] index of the word carrying the length in bytes of the + * buffer at this address, or one of the size-source sentinels + * below. se_val_cmd_addrs() uses the resulting length to confirm + * the whole buffer [addr, addr + len) fits inside the + * shared-memory window, not just its start. + * %SE_CMD_ADDR_FIXED_SIZE when the length is a firmware-defined + * literal supplied in @buf_size. + * %SE_CMD_RCVR_ADDR_VAR_SIZE when the length is taken from + * se_if_priv.cmd_rcvr_var_size (command-receiver responses). + * %SE_CMD_ADDR_DEDUCE_SZ when no length word is carried in the + * payload, but the buffer starts with a struct fw_tag_len_vers_info + * header whose length field gives the total buffer byte count; + * se_val_cmd_addrs() reads that header to range-check the whole + * buffer. + * @size_shift: right shift applied to the size word before masking, for a + * length packed into the high half of a word. + * @size_mask: bitmask applied after @size_shift to extract the length from + * the message word (0xFFFFFFFF for a full 32-bit length, 0xFFFF + * for a u16, 0xFF for a u8). Used only when @size_idx names a + * payload word; zero for the sentinel values. + * @buf_size: firmware-defined literal byte count. Used only when + * @size_idx == %SE_CMD_ADDR_FIXED_SIZE, where the whole buffer + * [addr, addr + @buf_size) must fit inside the shared-memory + * window. Left zero for every other @size_idx value. + */ +struct se_cmd_addr_field { + u8 lsb_idx; + u8 msb_idx; + bool has_msb; + u8 flag_idx; + u32 flag_mask; + bool is_addr_when_set; + u8 size_idx; + u8 size_shift; + u32 size_mask; + u32 buf_size; +}; + +#define SE_CMD_ADDR_ALWAYS 0xEFu +/* size is the literal in buf_size */ +#define SE_CMD_ADDR_FIXED_SIZE 0xFDu +/* size from se_if_priv.cmd_rcvr_var_size */ +#define SE_CMD_RCVR_ADDR_VAR_SIZE 0xFEu +/* size read from the buffer's fw_tag_len_vers_info header */ +#define SE_CMD_ADDR_DEDUCE_SZ 0xFFu + +int se_val_cmd_addrs(struct se_if_device_ctx *dev_ctx, struct se_api_msg *msg, + u32 tx_msg_sz, const struct se_cmd_addr_field *fields, + size_t count); + +const struct se_cmd_addr_field *ele_fw_cmd_addr_fields(u8 cmd, size_t *count); +const struct se_cmd_addr_field *ele_fw_rsp_addr_fields(u8 cmd, size_t *count); +const struct se_cmd_addr_field *ele_base_cmd_addr_fields(u8 cmd, size_t *count); /* Fill a command message header with a given command ID and length in bytes. */ static inline void se_fill_cmd_msg_hdr(struct se_if_priv *priv, struct se_msg_hdr *hdr, u8 cmd, u32 len, bool is_base_api) @@ -42,4 +139,9 @@ int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem); int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem); +int se_chk_tx_rsp_msg_hdr(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz); +int se_chk_tx_cmd_msg_hdr(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz, u32 rx_msg_sz); + #endif /*__ELE_COMMON_H__ */ diff --git a/drivers/firmware/imx/ele_fw_api.c b/drivers/firmware/imx/ele_fw_api.c new file mode 100644 index 000000000000..a3a68234bcb1 --- /dev/null +++ b/drivers/firmware/imx/ele_fw_api.c @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2026 NXP + */ + +#include + +#include "se_ctrl.h" +#include "ele_common.h" +#include "ele_fw_api.h" + +static int se_cmd_receiver_allowed_cmd(struct se_if_device_ctx *dev_ctx, + struct se_api_msg *msg, u32 tx_msg_sz) +{ + u8 cmd = msg->header.command; + + switch (cmd) { + case ELE_SESSION_CLOSE_REQ: + if (tx_msg_sz < ELE_SESSION_CLOSE_REQ_SZ || + msg->data[0] != dev_ctx->sess_hdl) + return -EINVAL; + return 0; + case ELE_STORAGE_CLOSE_REQ: + if (tx_msg_sz < ELE_STORAGE_CLOSE_REQ_SZ || + msg->data[0] != dev_ctx->strg_hdl) + return -EINVAL; + return 0; + case ELE_STORAGE_MASTER_IMPORT_REQ: { + const struct se_cmd_addr_field *fields; + size_t count; + + fields = ele_fw_cmd_addr_fields(cmd, &count); + return se_val_cmd_addrs(dev_ctx, msg, tx_msg_sz, fields, count); + } + default: + return -EOPNOTSUPP; + } +} + +static int se_cmd_receiver_allowed_rsp(struct se_if_device_ctx *dev_ctx, + struct se_api_msg *msg, u32 tx_msg_sz) +{ + struct cmd_rcvr_data_info *crcvr_info = &dev_ctx->priv->crcvr_info; + const struct se_cmd_addr_field *fields; + u8 cmd = msg->header.command; + size_t count; + + switch (cmd) { + case ELE_STORAGE_EXPORT_FINISH_REQ: + case ELE_STORAGE_CHUNK_GET_DONE_REQ: + case ELE_STORAGE_CHUNK_DELETE_REQ: + return 0; + default: + /* + * These responses supply a kernel buffer address to firmware. + * Range-check the embedded DMA address against the calling + * context's shared-memory window before the message is sent. + */ + if (crcvr_info->cmd_rcvr_last_rcvd_cmd_id != cmd) + return -EINVAL; + + fields = ele_fw_rsp_addr_fields(cmd, &count); + if (!count) + return -EOPNOTSUPP; + + return se_val_cmd_addrs(dev_ctx, msg, tx_msg_sz, fields, count); + } +} + +int ele_uapi_allowed_fw_rsp(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz) +{ + struct se_api_msg *msg = container_of(header, struct se_api_msg, header); + struct se_if_priv *priv = dev_ctx->priv; + + scoped_guard(mutex, &priv->modify_lock) + if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) + return -EINVAL; + + return se_cmd_receiver_allowed_rsp(dev_ctx, msg, tx_msg_sz); +} + +int ele_uapi_allowed_fw_cmd(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz, u32 rx_msg_sz) +{ + struct se_api_msg *msg = container_of(header, struct se_api_msg, header); + struct se_if_priv *priv = dev_ctx->priv; + const struct se_cmd_addr_field *fields; + bool receiver_exists = false; + bool is_cmd_receiver = false; + size_t count; + int ret = 0; + + scoped_guard(mutex, &priv->modify_lock) { + if (priv->cmd_receiver_clbk_hdl.dev_ctx) + receiver_exists = true; + if (dev_ctx == priv->cmd_receiver_clbk_hdl.dev_ctx) + is_cmd_receiver = true; + } + + if (is_cmd_receiver && header->tag == priv->if_defs->cmd_tag) + return se_cmd_receiver_allowed_cmd(dev_ctx, msg, tx_msg_sz); + + /* Reject any response message with non-command receiver */ + if (header->tag == priv->if_defs->rsp_tag) + return -EOPNOTSUPP; + + /* Reject any other tag */ + if (header->tag != priv->if_defs->cmd_tag) + return -EOPNOTSUPP; + + /* + * Identify the command first. Session/storage commands enforce their + * own-handle checks; crypto commands that embed DMA addresses defer to + * the shared range check below. Any command not named here is left with + * ret == 0 (permitted) as before. + */ + switch (header->command) { + case ELE_SESSION_OPEN_REQ: + /* Might be cleared as part of tear down. */ + ret = dev_ctx->sess_hdl ? -EEXIST : 0; + if (rx_msg_sz < ELE_SESSION_OPEN_RSP_SZ) + ret = -EINVAL; + break; + case ELE_SESSION_CLOSE_REQ: + /* Might be cleared as part of tear down. */ + if (!dev_ctx->sess_hdl) { + ret = -ENXIO; + break; + } + /* + * A close request must target this context's own session. The + * handle to close is carried in the payload (data[0]); reject a + * request whose buffer is too short to hold it, or whose handle + * does not match this context. Checking the buffer size first + * also keeps the data[0] read in bounds. This stops one process + * from closing - and leaking - another process's session with a + * spoofed handle. + */ + if (tx_msg_sz < ELE_SESSION_CLOSE_REQ_SZ || + msg->data[0] != dev_ctx->sess_hdl) + ret = -EINVAL; + break; + case ELE_FW_GET_INFO_REQ: + case ELE_KEY_STORE_OPEN_REQ: + case ELE_KEY_STORE_CLOSE_REQ: + case ELE_KEY_MGMT_OPEN_REQ: + case ELE_KEY_MGMT_CLOSE_REQ: + case ELE_MANAGE_KEY_GROUP_REQ: + case ELE_GET_KEY_ATTR_REQ: + case ELE_KEY_DELETE_REQ: + case ELE_MAC_OPEN_REQ: + case ELE_MAC_CLOSE_REQ: + case ELE_CIPHER_OPEN_REQ: + case ELE_CIPHER_CLOSE_REQ: + case ELE_SIGNATURE_GENERATE_OPEN_REQ: + case ELE_SIGNATURE_GENERATE_CLOSE_REQ: + case ELE_SIGNATURE_VERIFY_OPEN_REQ: + case ELE_SIGNATURE_VERIFY_CLOSE_REQ: + case ELE_DATA_STORAGE_OPEN_REQ: + case ELE_DATA_STORAGE_CLOSE_REQ: + case ELE_DATA_DELETE_REQ: + ret = 0; + break; + case ELE_STORAGE_OPEN_REQ: + /* Might be cleared as part of tear down. */ + if (dev_ctx->strg_hdl) { + ret = -EEXIST; + break; + } + /* + * NOTE: this advisory early check is intentionally not the + * definitive exclusivity gate. modify_lock is dropped before the + * command is sent, creating a TOCTOU window. That window is + * closed by two additional layers: + * 1. se_if_cmd_lock, held for the full send+receive cycle, so + * only one ELE_STORAGE_OPEN_REQ is in flight per MU at a + * time. + * 2. set_dev_ctx_as_command_receiver(), which re-checks under + * modify_lock after the response arrives. If two callers + * race past this check, FW itself rejects the second + * ELE_STORAGE_OPEN_REQ before any handle is allocated. + * See Documentation/driver-api/firmware/other_interfaces.rst, + * section "ELE_STORAGE_OPEN_REQ concurrency and + * command-receiver exclusivity". + */ + if (receiver_exists && !is_cmd_receiver) + ret = -EBUSY; + if (rx_msg_sz < ELE_STORAGE_OPEN_RSP_SZ) + ret = -EINVAL; + break; + case ELE_STORAGE_CLOSE_REQ: + /* Might be cleared as part of tear down. */ + if (!dev_ctx->strg_hdl) { + ret = -ENXIO; + break; + } + /* Same self-ownership check as the session close above. */ + if (tx_msg_sz < ELE_STORAGE_CLOSE_REQ_SZ || + msg->data[0] != dev_ctx->strg_hdl) + ret = -EINVAL; + break; + case ELE_STORAGE_STATUS_REQ: + ret = 0; + break; + default: + /* FW commands that embed DMA addresses. */ + fields = ele_fw_cmd_addr_fields(header->command, &count); + if (!count) { + ret = -EOPNOTSUPP; + break; + } + + ret = se_val_cmd_addrs(dev_ctx, msg, tx_msg_sz, fields, count); + break; + } + + return ret; +} + +void cmd_receiver_specific_ops(struct se_if_device_ctx *dev_ctx, + struct se_api_msg *rx_msg) +{ + struct cmd_rcvr_data_info *crcvr_info = &dev_ctx->priv->crcvr_info; + struct se_msg_hdr *header = &rx_msg->header; + + crcvr_info->cmd_rcvr_last_rcvd_cmd_id = 0; + crcvr_info->cmd_rcvr_var_size = 0; + switch (header->command) { + case ELE_STORAGE_MASTER_EXPORT_REQ: + /* + * FW sent an export-start command with key_store_size at + * data[1]. Save it so se_val_cmd_addrs() can range-check the + * response buffer when the cmd_receiver sends back the address. + */ + crcvr_info->cmd_rcvr_last_rcvd_cmd_id = ELE_STORAGE_MASTER_EXPORT_REQ; + crcvr_info->cmd_rcvr_var_size = rx_msg->data[1]; + break; + case ELE_STORAGE_CHUNK_EXPORT_REQ: + /* + * FW sent a chunk-export command with chunk_size at data[1]. + * Save it so se_val_cmd_addrs() can range-check the response + * buffer when the cmd_receiver sends back the address. + */ + crcvr_info->cmd_rcvr_last_rcvd_cmd_id = ELE_STORAGE_CHUNK_EXPORT_REQ; + crcvr_info->cmd_rcvr_var_size = rx_msg->data[1]; + break; + case ELE_STORAGE_CHUNK_GET_REQ: + crcvr_info->cmd_rcvr_last_rcvd_cmd_id = ELE_STORAGE_CHUNK_GET_REQ; + break; + } +} + +int fw_api_specific_ops(struct se_if_device_ctx *dev_ctx, struct se_api_msg *rx_msg, + bool is_cmd_interrupted) +{ + struct se_msg_hdr *header = &rx_msg->header; + struct se_if_priv *priv = dev_ctx->priv; + + switch (header->command) { + case ELE_SESSION_OPEN_REQ: + dev_ctx->sess_hdl = rx_msg->data[1]; + if (is_cmd_interrupted) { + if (se_close_session(dev_ctx, dev_ctx->sess_hdl)) + dev_err(dev_ctx->priv->dev, "failed to close session.\n"); + dev_ctx->sess_hdl = 0; + } + break; + case ELE_SESSION_CLOSE_REQ: + dev_ctx->sess_hdl = 0; + break; + case ELE_STORAGE_OPEN_REQ: { + int rc; + + /* + * Record the storage handle before registering as command + * receiver. FW has already allocated the handle; if we assigned + * it only after a successful registration, a failing + * set_dev_ctx_as_command_receiver() (e.g. -EBUSY) would leave + * strg_hdl at 0 while the ioctl still returns success to + * userspace. The kernel would then never close the handle on + * teardown, leaking it in FW. Storing it first guarantees + * cleanup_dev_ctx() closes it on the next close(), regardless + * of whether registration succeeded. + */ + dev_ctx->strg_hdl = rx_msg->data[1]; + + rc = is_cmd_interrupted ? 0 : set_dev_ctx_as_command_receiver(dev_ctx); + if (is_cmd_interrupted || rc) { + if (se_close_storage(dev_ctx, dev_ctx->strg_hdl)) + dev_err(dev_ctx->priv->dev, "failed to close storage.\n"); + dev_ctx->strg_hdl = 0; + if (rc) + dev_err(priv->dev, + "Failed to register %s as CMD-Receiver: %d\n", + dev_ctx->devname, rc); + return rc; + } + break; + } + case ELE_STORAGE_CLOSE_REQ: + scoped_guard(mutex, &priv->modify_lock) + unset_dev_ctx_as_command_receiver(dev_ctx); + dev_ctx->strg_hdl = 0; + break; + } + + return 0; +} + +int se_close_session(struct se_if_device_ctx *dev_ctx, u32 session_hdl) +{ + struct se_api_msg *tx_msg __free(kfree) = + kzalloc(ELE_SESSION_CLOSE_REQ_SZ, GFP_KERNEL); + struct se_api_msg *rx_msg __free(kfree) = + kzalloc(ELE_SESSION_CLOSE_RSP_SZ, GFP_KERNEL); + struct se_if_priv *priv; + int ret; + + if (!dev_ctx || !dev_ctx->priv) + return -EINVAL; + + if (!tx_msg || !rx_msg) + return -ENOMEM; + + priv = dev_ctx->priv; + + /* + * Session close is a FW-API command; pass is_base_api=false so the + * header carries fw_api_ver. + */ + se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, + ELE_SESSION_CLOSE_REQ, ELE_SESSION_CLOSE_REQ_SZ, false); + + tx_msg->data[0] = session_hdl; + + /* + * Transmit on the caller's own context. Using dev_ctx (rather than + * hardcoding priv->priv_dev_ctx) keeps a userspace close() subject to + * the going_away check in ele_msg_send_rcv(): if unbind has begun and + * freed priv->tx_chan, the send is rejected with -ENODEV instead of + * touching the freed mailbox channel. + * + * The teardown and fw_busy-recovery paths instead reserve the messaging + * interface for their own task via se_reserve_msg_if() before calling + * this. That reservation (msg_excl_owner == current) is what makes + * ele_msg_send_rcv() let their resync closes through the going_away and + * fw_busy gates; they also pass priv_dev_ctx so the wait is the + * uninterruptible internal-context wait. + */ + + ret = ele_msg_send_rcv(dev_ctx, + tx_msg, + ELE_SESSION_CLOSE_REQ_SZ, + rx_msg, + ELE_SESSION_CLOSE_RSP_SZ, NULL); + if (ret < 0) + return ret; + + ret = se_val_rsp_hdr_n_status(dev_ctx, + rx_msg, + ELE_SESSION_CLOSE_REQ, + ELE_SESSION_CLOSE_RSP_SZ, + priv->if_defs->fw_api_ver); + return ret; +} + +int se_close_storage(struct se_if_device_ctx *dev_ctx, u32 storage_hdl) +{ + struct se_api_msg *tx_msg __free(kfree) = + kzalloc(ELE_STORAGE_CLOSE_REQ_SZ, GFP_KERNEL); + struct se_api_msg *rx_msg __free(kfree) = + kzalloc(ELE_STORAGE_CLOSE_RSP_SZ, GFP_KERNEL); + struct se_if_priv *priv; + int ret; + + if (!dev_ctx || !dev_ctx->priv) + return -EINVAL; + + if (!tx_msg || !rx_msg) + return -ENOMEM; + + priv = dev_ctx->priv; + + /* Same FW-API version handling as se_close_session() above. */ + se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header, + ELE_STORAGE_CLOSE_REQ, ELE_STORAGE_CLOSE_REQ_SZ, false); + + tx_msg->data[0] = storage_hdl; + + /* Transmit on the caller's own context; see se_close_session(). */ + ret = ele_msg_send_rcv(dev_ctx, + tx_msg, + ELE_STORAGE_CLOSE_REQ_SZ, + rx_msg, + ELE_STORAGE_CLOSE_RSP_SZ, NULL); + if (ret < 0) + return ret; + + ret = se_val_rsp_hdr_n_status(dev_ctx, + rx_msg, + ELE_STORAGE_CLOSE_REQ, + ELE_STORAGE_CLOSE_RSP_SZ, + priv->if_defs->fw_api_ver); + return ret; +} diff --git a/drivers/firmware/imx/ele_fw_api.h b/drivers/firmware/imx/ele_fw_api.h new file mode 100644 index 000000000000..7a6d7dab84ff --- /dev/null +++ b/drivers/firmware/imx/ele_fw_api.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2026 NXP + */ + +#ifndef ELE_FW_API_H +#define ELE_FW_API_H +#include "se_ctrl.h" + +#define ELE_SESSION_OPEN_REQ 0x10u +#define ELE_SESSION_OPEN_RSP_SZ 0x0Cu + +#define ELE_SESSION_CLOSE_REQ_SZ 0x08u +#define ELE_SESSION_CLOSE_RSP_SZ 0x08u +#define ELE_SESSION_CLOSE_REQ 0x11u + +/* + * Session-scoped FW-API service, key-management and close command opcodes + * (SAB command IDs, PSA_COMPLIANT message layout). These commands do not + * embed DMA staging-buffer addresses that require range-checking; they are + * defined here for completeness and for use by the command allow-list. + * ELE_FW_GET_INFO_REQ is the FW-API get-info opcode and is intentionally + * distinct from the base-API ELE_GET_INFO_REQ (0xda) in ele_base_msg.h. + */ +#define ELE_FW_GET_INFO_REQ 0x16u +#define ELE_KEY_STORE_OPEN_REQ 0x30u +#define ELE_KEY_STORE_CLOSE_REQ 0x31u +#define ELE_KEY_MGMT_OPEN_REQ 0x40u +#define ELE_KEY_MGMT_CLOSE_REQ 0x41u +#define ELE_MANAGE_KEY_GROUP_REQ 0x45u +#define ELE_GET_KEY_ATTR_REQ 0x4Cu +#define ELE_KEY_DELETE_REQ 0x4Eu +#define ELE_MAC_OPEN_REQ 0x50u +#define ELE_MAC_CLOSE_REQ 0x51u +#define ELE_CIPHER_OPEN_REQ 0x60u +#define ELE_CIPHER_CLOSE_REQ 0x61u +#define ELE_SIGNATURE_GENERATE_OPEN_REQ 0x70u +#define ELE_SIGNATURE_GENERATE_CLOSE_REQ 0x71u +#define ELE_SIGNATURE_VERIFY_OPEN_REQ 0x80u +#define ELE_SIGNATURE_VERIFY_CLOSE_REQ 0x81u +#define ELE_DATA_STORAGE_OPEN_REQ 0xA0u +#define ELE_DATA_STORAGE_CLOSE_REQ 0xA1u +#define ELE_DATA_DELETE_REQ 0xA4u + +/* + * FW-API crypto command opcodes that embed one or more DMA physical addresses + * in their message payload. ele_uapi_allowed_fw_cmd() range-checks those + * addresses against the calling context's shared-memory window before the + * message is handed to firmware. Opcodes match the SAB command IDs emitted by + * the userspace library (PSA_COMPLIANT message layout). + */ +#define ELE_PUB_KEY_EXPORT_REQ 0x32u +#define ELE_KEYSTORE_REPROV_ENABLE_REQ 0x3Fu +#define ELE_KEYGEN_REQ 0x42u +#define ELE_KEY_EXCHANGE_REQ 0x47u +#define ELE_KEY_IMPORT_REQ 0x4Fu +#define ELE_KEY_IMPORT 0x4Fu +#define ELE_MAC_REQ 0x52u +#define ELE_CIPHER_REQ 0x62u +#define ELE_AUTH_ENC_REQ 0x64u +#define ELE_AUTH_ENC_NEW_REQ 0x65u +#define ELE_SIGNATURE_GENERATE_REQ 0x72u +#define ELE_PUB_KEY_ATTEST_REQ 0x74u +#define ELE_SIGNATURE_VERIFY_REQ 0x82u +#define ELE_DATA_STORAGE_REQ 0xA2u +#define ELE_ENC_DATA_STORAGE_REQ 0xA3u +#define ELE_ASYMMETRIC_ENC_REQ 0x92u + +#define ELE_KEY_GENERIC_CRYPTO_REQ 0xC2u +#define ELE_GC_CIPHER_REQ 0xC8u +#define ELE_GC_AEAD_REQ 0xC9u +#define ELE_GC_ACRYPTO_REQ 0xCAu +#define ELE_GC_AKEY_GEN_REQ 0xCBu +#define ELE_HASH_ONE_GO_REQ 0xCCu +#define ELE_RNG_GET_RANDOM_REQ 0xCDu + +#define ELE_STORAGE_OPEN_REQ 0xE0u +#define ELE_STORAGE_OPEN_RSP_SZ 0x0Cu + +#define ELE_STORAGE_CLOSE_REQ_SZ 0x08u +#define ELE_STORAGE_CLOSE_RSP_SZ 0x08u +#define ELE_STORAGE_CLOSE_REQ 0xE1u + +#define ELE_STORAGE_MASTER_IMPORT_REQ 0xE2u +#define ELE_STORAGE_MASTER_EXPORT_REQ 0xE3u +#define ELE_STORAGE_EXPORT_FINISH_REQ 0xE4u +#define ELE_STORAGE_CHUNK_EXPORT_REQ 0xE5u +#define ELE_STORAGE_CHUNK_GET_REQ 0xE6u +#define ELE_STORAGE_CHUNK_GET_DONE_REQ 0xE7u +#define ELE_STORAGE_CHUNK_DELETE_REQ 0xE9u +#define ELE_STORAGE_STATUS_REQ 0xEAu + +int ele_uapi_allowed_fw_rsp(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz); +int ele_uapi_allowed_fw_cmd(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header, + u32 tx_msg_sz, u32 rx_msg_sz); +int fw_api_specific_ops(struct se_if_device_ctx *dev_ctx, struct se_api_msg *rx_msg, + bool is_cmd_interrupted); +void cmd_receiver_specific_ops(struct se_if_device_ctx *dev_ctx, + struct se_api_msg *rx_msg); +int se_close_session(struct se_if_device_ctx *dev_ctx, u32 session_hdl); +int se_close_storage(struct se_if_device_ctx *dev_ctx, u32 storage_hdl); + +#endif /* ELE_FW_API_H */ diff --git a/drivers/firmware/imx/ele_msg_addr_field.c b/drivers/firmware/imx/ele_msg_addr_field.c new file mode 100644 index 000000000000..ac49ac78da68 --- /dev/null +++ b/drivers/firmware/imx/ele_msg_addr_field.c @@ -0,0 +1,619 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2026 NXP + */ + +#include + +#include "ele_common.h" +#include "ele_base_msg.h" +#include "ele_fw_api.h" + +/* + * Base-API commands that embed one or more DMA physical addresses in their + * payload. Unlike the FW-API crypto commands, GET_INFO and DEV_ATTEST split + * their response-buffer address across two words: the high half is written + * first (lower word index) and the low half next, so has_msb is set and the + * msb_idx precedes the lsb_idx. GEN_KEY_BLOB uses single-word LSB addresses. + * See struct se_cmd_addr_field in ele_common.h for the field semantics. + */ +static const struct se_cmd_addr_field ele_get_info_addr_fields[] = { + /* + * rsp_data_addr_hi @ data[0], rsp_data_addr_lo @ data[1]; + * buf_sz is a u16 in the low half of data[2]. + */ + { .lsb_idx = 1, .msb_idx = 0, .has_msb = true, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFu }, +}; + +static const struct se_cmd_addr_field ele_dev_attest_addr_fields[] = { + /* + * rsp_data_addr_hi @ data[0], rsp_data_addr_lo @ data[1]; + * buf_sz is a u16 in the low half of data[2]. + */ + { .lsb_idx = 1, .msb_idx = 0, .has_msb = true, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFu }, +}; + +static const struct se_cmd_addr_field ele_oem_auth_cntr_addr_fields[] = { + /* + * Container Header address: a 64-bit physical address split across two + * words. data[0] holds the 32-bit MSB and data[1] holds the 32-bit LSB + * (ELE API spec Table 27, word size = 0x3, so the command is header + + * MSB + LSB only). No length word is carried in the payload; the buffer + * length is read from the fw_tag_len_vers_info header at its start + * (SE_CMD_ADDR_DEDUCE_SZ) so the whole buffer is range-checked. + */ + { .lsb_idx = 1, .msb_idx = 0, .has_msb = true, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = SE_CMD_ADDR_DEDUCE_SZ }, /* container_hdr_addr */ +}; + +/* + * GENERATE ELE KEY BLOB command (ELE_GEN_KEY_BLOB_REQ, 0xAF). + * ELE API spec Table 73, word size = 0x8 (header + 7 data words): + * data[0] = key_identifier + * data[1] = Reserved + * data[2] = load_address (32-bit; must be 64-bit aligned) + * data[3] = Reserved + * data[4] = store_address (32-bit; must be 64-bit aligned) + * data[5] = Reserved[31:16] | max_export_size[15:0] + * data[6] = CRC + * + * load_addr points to the input: a blob header (8 bytes, Table 77) followed + * by the plaintext payload. No size word is present in the message for this + * input buffer. The maximum input size is determined by the largest supported + * payload type: OTFAD key configuration (0x28 bytes per Table 79) plus the + * 8-byte header gives 0x30 bytes. That is the literal upper bound placed in + * buf_size and selected with SE_CMD_ADDR_FIXED_SIZE, so se_val_cmd_addrs() + * can verify [load_addr, load_addr+0x30) lies within the shared-memory + * window. + */ +#define OP_GEN_ELE_KEY_BLOB_INPUT_MAX_SZ 0x30 /* blob hdr (8) + OTFAD payload (0x28) */ +static const struct se_cmd_addr_field ele_gen_key_blob_addr_fields[] = { + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = SE_CMD_ADDR_FIXED_SIZE, + .buf_size = OP_GEN_ELE_KEY_BLOB_INPUT_MAX_SZ }, /* load_address */ + /* store_address @ data[4]; max_export_size is u16 in low half of data[5] */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFu }, /* store_address */ +}; + +/* + * Return the address-field descriptor table for a base-API command, or NULL + * when the command embeds no DMA addresses. count is set to the number of + * entries. + */ +const struct se_cmd_addr_field *ele_base_cmd_addr_fields(u8 cmd, size_t *count) +{ + switch (cmd) { + case ELE_OEM_AUTH_CONTAINER_REQ: + *count = ARRAY_SIZE(ele_oem_auth_cntr_addr_fields); + return ele_oem_auth_cntr_addr_fields; + case ELE_GEN_KEY_BLOB_REQ: + *count = ARRAY_SIZE(ele_gen_key_blob_addr_fields); + return ele_gen_key_blob_addr_fields; + case ELE_GET_INFO_REQ: + *count = ARRAY_SIZE(ele_get_info_addr_fields); + return ele_get_info_addr_fields; + case ELE_DEV_ATTEST_REQ: + *count = ARRAY_SIZE(ele_dev_attest_addr_fields); + return ele_dev_attest_addr_fields; + default: + *count = 0; + return NULL; + } +} + +/* + * FW-API crypto commands that embed one or more DMA physical addresses in + * their payload. On the PSA_COMPLIANT ABI most addresses are written by the + * userspace library as a single little-endian 32-bit LSB word (the high half + * is always zero), so has_msb is left false for those entries. A few commands + * (pub-key-export 0x32, keystore reprov-enable 0x3F) carry an explicit ext/MSB + * word ahead of the LSB word, matching the base-API two-word address layout; + * their entries set has_msb = true so the MSB word is validated too. See + * struct se_cmd_addr_field in ele_common.h for the field semantics. + */ +static const struct se_cmd_addr_field ele_pub_key_export_addr_fields[] = { + /* + * out_key_addr: the recovered public key output buffer. Its high half + * out_key_addr_ext is data[2] and its low half out_key_addr is data[3]; + * the library always writes it via set_phy_addr_to_words(), so it is + * always a DMA address. Its length is out_key_size, the u16 in the low + * half of data[4]. key_identifier (data[1]) is an integer, not an + * address. + */ + { .lsb_idx = 3, .msb_idx = 2, .has_msb = true, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFu }, /* out_key_addr */ +}; + +static const struct se_cmd_addr_field ele_keystore_reprov_en_addr_fields[] = { + /* + * Signed message address: a 64-bit physical address split across two + * words. data[0] holds the 32-bit MSB and data[1] holds the 32-bit LSB + * (ELE API spec Table 202, word size = 0x3, so the command is header + + * MSB + LSB only). No length word is carried in the payload; the buffer + * length is read from the fw_tag_len_vers_info header at its start + * (SE_CMD_ADDR_DEDUCE_SZ) so the whole buffer is range-checked. + */ + { .lsb_idx = 1, .msb_idx = 0, .has_msb = true, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = SE_CMD_ADDR_DEDUCE_SZ }, /* signed_msg_addr */ +}; + +static const struct se_cmd_addr_field ele_keygen_addr_fields[] = { + /* + * key @ data[1]: a plaintext private-key output buffer only when the + * KEY_GENERATION PLAINTEXT_KEY flag (bit 3 of the flags byte in the low + * 8 bits of data[8]) is set; otherwise it is an integer key identifier. + * Its length is priv_key_sz, the u16 in the high half of data[8]. + */ + { .lsb_idx = 1, .flag_idx = 8, .flag_mask = 0x00000008u, .is_addr_when_set = true, + .size_idx = 8, .size_shift = 16, .size_mask = 0xFFFFu }, /* priv_key_addr */ + /* + * pub_key_addr @ data[9]: always a DMA address. Its length is + * pub_key_sz, the u16 in the low half of data[2]. + */ + { .lsb_idx = 9, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFu }, /* pub_key_addr */ +}; + +static const struct se_cmd_addr_field ele_key_exchange_addr_fields[] = { + /* + * PSA_COMPLIANT key-exchange payload. key_management_handle is data[0] + * and flags/reserved is data[1]; the four buffer addresses that follow + * are each written unconditionally via set_phy_addr_to_words() (single + * LSB word, high half always zero), so all are always DMA addresses. + * Each address is immediately followed by its full u32 byte length. + */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_mask = 0xFFFFFFFFu }, /* in_content_addr */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFFFFFu }, /* in_pub_buffer_addr */ + { .lsb_idx = 6, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 7, .size_mask = 0xFFFFFFFFu }, /* user_fixed_info_addr */ + { .lsb_idx = 8, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFFFFFu }, /* output_addr */ +}; + +static const struct se_cmd_addr_field ele_key_import_addr_fields[] = { + /* + * PSA_COMPLIANT key-import payload. key_management_handle is data[0] + * and flags/reserved is data[1]; the single input buffer address that + * follows is written unconditionally via set_phy_addr_to_words() + * (single LSB word, high half always zero), so it is always a DMA + * address. Its length is the full u32 input_size in data[3]. + */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_mask = 0xFFFFFFFFu }, /* input_address */ +}; + +/* ELE_MAC_REQ: MAC one-go operation. */ +static const struct se_cmd_addr_field ele_mac_addr_fields[] = { + /* key: plaintext-key buffer only when the MAC PLAINTEXT_KEY flag is set */ + { .lsb_idx = 1, .flag_idx = 5, .flag_mask = 0x00080000u, .is_addr_when_set = true, + .size_idx = 7, .size_mask = 0xFFFFu }, /* key_size */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* payload_address */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFu }, /* mac_address */ + { .lsb_idx = 8, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFu }, /* context_address */ +}; + +/* ELE_CIPHER_REQ: symmetric cipher one-go operation. */ +static const struct se_cmd_addr_field ele_cipher_addr_fields[] = { + /* key: plaintext-key buffer only when the CIPHER PLAINTEXT_KEY flag is set */ + { .lsb_idx = 1, .flag_idx = 3, .flag_mask = 0x00080000u, .is_addr_when_set = true, + .size_idx = 9, .size_mask = 0xFFFFu }, /* key_size */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_mask = 0xFFFFu }, /* iv_address */ + { .lsb_idx = 5, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 7, .size_mask = 0xFFFFFFFFu }, /* input_address */ + { .lsb_idx = 6, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 8, .size_mask = 0xFFFFFFFFu }, /* output_address */ + { .lsb_idx = 10, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 11, .size_mask = 0xFFFFu }, /* context_address */ +}; + +/* + * AEAD encrypt/decrypt legacy command (ELE_AUTH_ENC_REQ, 0x64). + * ELE API spec Table 287, word size = 0xD (header + 12 data words): + * data[0] = cipher_handle + * data[1] = key_identifier + * data[2] = IV LSB address + * data[3] = Reserved[31:24] | Flags[23:16] | IV_size[15:0] + * data[4] = algorithm + * data[5] = AAD LSB address + * data[6] = Reserved[31:16] | AAD_size[15:0] + * data[7] = Input LSB address + * data[8] = Output LSB address + * data[9] = Input size (u32) + * data[10] = Output size (u32) + * data[11] = CRC + * IV size is the 16-bit low half of data[3]; AAD size is the 16-bit low half + * of data[6]; input and output sizes are full u32 words. + */ +static const struct se_cmd_addr_field ele_auth_enc_addr_fields[] = { + /* iv_address (size[15:0] @ data[3]) */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_mask = 0xFFFFu }, + /* aad_address (size[15:0] @ data[6]) */ + { .lsb_idx = 5, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 6, .size_mask = 0xFFFFu }, + /* input_address (size[31:0] @ data[9]) */ + { .lsb_idx = 7, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFFFFFu }, + /* output_address (size[31:0] @ data[10]) */ + { .lsb_idx = 8, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 10, .size_mask = 0xFFFFFFFFu }, +}; + +/* ELE_AUTH_ENC_NEW_REQ: AEAD encrypt/decrypt with internally-generated IV output. */ +#define ELE_AUTH_ENC_IV_OUT_SIZE 12 /* firmware always writes exactly 12 bytes */ +static const struct se_cmd_addr_field ele_auth_enc_new_addr_fields[] = { + /* iv_address_in length is packed in the high half of the iv-size word */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_shift = 16, .size_mask = 0xFFFFu }, /* iv_address_in */ + /* iv_address_out has a fixed firmware-defined length, not carried in msg */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = SE_CMD_ADDR_FIXED_SIZE, + .buf_size = ELE_AUTH_ENC_IV_OUT_SIZE }, /* iv_address_out */ + /* key: plaintext-key buffer only when the PLAINTEXT_KEY flag is set */ + { .lsb_idx = 5, .flag_idx = 2, .flag_mask = 0x00000008u, .is_addr_when_set = true, + .size_idx = 7, .size_shift = 16, .size_mask = 0xFFFFu }, /* key_size */ + { .lsb_idx = 6, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 7, .size_mask = 0xFFFFu }, /* tag_address */ + { .lsb_idx = 8, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFFFFFu }, /* aad_address */ + { .lsb_idx = 10, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 11, .size_mask = 0xFFFFFFFFu }, /* input_address */ + { .lsb_idx = 12, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 13, .size_mask = 0xFFFFFFFFu }, /* output_address */ + { .lsb_idx = 14, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 15, .size_mask = 0xFFFFu }, /* context_address */ +}; + +/* ELE_SIGNATURE_GENERATE_REQ: digital signature generation. */ +static const struct se_cmd_addr_field ele_sign_gen_addr_fields[] = { + /* key: plaintext-key buffer only when GENERATE_SIGN PLAINTEXT_KEY is set */ + { .lsb_idx = 1, .flag_idx = 5, .flag_mask = 0x00080000u, .is_addr_when_set = true, + .size_idx = 8, .size_mask = 0xFFFFu }, /* priv_key_size */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* message_addr */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFu }, /* signature_addr */ + { .lsb_idx = 9, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 11, .size_mask = 0xFFFFu }, /* sm2_pub_key_addr */ + { .lsb_idx = 10, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 11, .size_shift = 16, + .size_mask = 0xFFFFu }, /* sm2_id / ml_dsa_ctx addr */ +}; + +static const struct se_cmd_addr_field ele_pub_key_attest_addr_fields[] = { + /* + * PSA_COMPLIANT public-key-attestation payload. sig_gen_hdl is data[0], + * key_identifier data[1], key_attestation_id data[2], attest_algo + * data[3]. The two buffer addresses that follow are each written + * unconditionally via set_phy_addr_to_words() (single LSB word, high + * half always zero), so both are always DMA addresses. Each address is + * immediately followed by its full u32 byte length. + */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFFFFFu }, /* auth_challenge_addr */ + { .lsb_idx = 6, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 7, .size_mask = 0xFFFFFFFFu }, /* certificate_addr */ +}; + +/* ELE_SIGNATURE_VERIFY_REQ: digital signature verification. */ +static const struct se_cmd_addr_field ele_verify_sign_addr_fields[] = { + /* key: plaintext-key buffer unless the VERIFY_SIGN OPAQUE_KEY flag is set */ + { .lsb_idx = 1, .flag_idx = 7, .flag_mask = 0x00000008u, .is_addr_when_set = false, + .size_idx = 5, .size_shift = 16, .size_mask = 0xFFFFu }, /* key_size */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* msg_addr */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFu }, /* sig_addr */ + { .lsb_idx = 10, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 11, .size_mask = 0xFFFFu }, /* sm2_id / ml_dsa_ctx addr */ +}; + +static const struct se_cmd_addr_field ele_data_storage_addr_fields[] = { + /* + * PSA_COMPLIANT data-storage payload. data_storage_handle is data[0], + * flags/reserved is data[1], data_id is data[2]. data_address (data[3]) + * is the plaintext data buffer, written unconditionally via + * set_phy_addr_to_words() (single LSB word, high half always zero), so + * it is always a DMA address. Its length is the full u32 data_size in + * data[4]. + */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* data_address */ +}; + +/* ELE_ASYMMETRIC_ENC_REQ: asymmetric encryption/decryption. */ +static const struct se_cmd_addr_field ele_asym_enc_addr_fields[] = { + /* key_id_addr: plaintext-key buffer only when the PLAINTEXT_KEY flag is set */ + { .lsb_idx = 1, .flag_idx = 8, .flag_mask = 0x00000008u, .is_addr_when_set = true, + .size_idx = 10, .size_mask = 0xFFFFFFFFu }, /* input_plainkey_size */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFFFFFu }, /* plaintext_addr */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 6, .size_mask = 0xFFFFFFFFu }, /* ciphertext_addr */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 7, .size_mask = 0xFFFFFFFFu }, /* label_addr */ +}; + +/* ELE_KEY_GENERIC_CRYPTO_REQ: generic crypto operation with a raw key. */ +static const struct se_cmd_addr_field ele_key_generic_crypto_addr_fields[] = { + /* key_address length is the u8 key_size in the third byte of the iv-size word */ + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_shift = 16, .size_mask = 0xFFu }, /* key_address */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_mask = 0xFFFFu }, /* iv_address */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFu }, /* aad_address */ + { .lsb_idx = 6, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 8, .size_mask = 0xFFFFFFFFu }, /* input_address */ + { .lsb_idx = 7, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFFFFFu }, /* output_address */ +}; + +/* ELE_GC_CIPHER_REQ: GC symmetric cipher operation. */ +static const struct se_cmd_addr_field ele_gc_cipher_addr_fields[] = { + { .lsb_idx = 0, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFFFFFu }, /* in_addr */ + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFFFFFu }, /* out_addr (shares data_size) */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* key_addr */ + { .lsb_idx = 5, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 6, .size_mask = 0xFFFFFFFFu }, /* iv_addr */ +}; + +/* ELE_GC_AEAD_REQ: GC AEAD operation. */ +static const struct se_cmd_addr_field ele_gc_aead_addr_fields[] = { + { .lsb_idx = 0, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFFFFFu }, /* in_addr */ + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFFFFFu }, /* out_addr (shares data_size) */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* key_addr */ + { .lsb_idx = 5, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 6, .size_mask = 0xFFFFFFFFu }, /* nonce_addr */ + { .lsb_idx = 7, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 8, .size_mask = 0xFFFFFFFFu }, /* aad_addr */ + { .lsb_idx = 9, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 10, .size_mask = 0xFFFFFFFFu }, /* tag_addr */ +}; + +/* ELE_GC_ACRYPTO_REQ: GC asymmetric crypto operation. */ +static const struct se_cmd_addr_field ele_gc_acrypto_addr_fields[] = { + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFFFFFu }, /* data_buff1_addr */ + { .lsb_idx = 4, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 6, .size_mask = 0xFFFFFFFFu }, /* data_buff2_addr */ + { .lsb_idx = 7, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFu }, /* key_buff1_addr */ + { .lsb_idx = 8, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_shift = 16, .size_mask = 0xFFFFu }, /* key_buff2_addr */ + { .lsb_idx = 12, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 13, .size_mask = 0xFFFFu }, /* rsa_label_addr */ +}; + +/* ELE_GC_AKEY_GEN_REQ: GC asymmetric key generation. */ +static const struct se_cmd_addr_field ele_gc_akey_gen_addr_fields[] = { + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFu }, /* modulus_addr */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_shift = 16, .size_mask = 0xFFFFu }, /* priv_buff_addr */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFu }, /* pub_buff_addr */ +}; + +/* ELE_HASH_ONE_GO_REQ: hash one-go operation. */ +static const struct se_cmd_addr_field ele_hash_one_go_addr_fields[] = { + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 6, .size_shift = 16, .size_mask = 0xFFFFu }, /* ctx_addr */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 4, .size_mask = 0xFFFFFFFFu }, /* input_addr */ + { .lsb_idx = 3, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 5, .size_mask = 0xFFFFFFFFu }, /* output_addr */ +}; + +static const struct se_cmd_addr_field ele_enc_data_storage_addr_fields[] = { + /* + * PSA_COMPLIANT encrypted-data-storage payload. data_storage_handle is + * data[0] and data_id is data[1]. data_address (data[2]) is written + * unconditionally via set_phy_addr_to_words() (single LSB word, high + * half always zero), so it is always a DMA address; its length is the + * full u32 data_size in data[3]. iv_address (data[8]) is only written + * when an IV is supplied and is left zero otherwise, so it is an + * optional always-address handled by the zero-address skip; its length + * is the u16 iv_size in the low half of data[9]. + */ + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 3, .size_mask = 0xFFFFFFFFu }, /* data_address */ + { .lsb_idx = 8, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 9, .size_mask = 0xFFFFu }, /* iv_address */ +}; + +static const struct se_cmd_addr_field ele_rng_get_random_addr_fields[] = { + /* + * PSA_COMPLIANT get-random payload. reserved/flags is data[0]; rnd_addr + * (data[1]) is the output buffer, written unconditionally via + * set_phy_addr_to_words() (single LSB word, high half always zero), so + * it is always a DMA address. Its length is the full u32 rnd_size in + * data[2]. + */ + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFFFFFu }, /* rnd_addr */ +}; + +static const struct se_cmd_addr_field ele_storage_master_import_addr_fields[] = { + /* + * Storage master-import command (ELE_STORAGE_MASTER_IMPORT_REQ). + * Payload layout (data[] = message word minus header word 0): + * data[0] = storage_handle + * data[1] = key_store_address (LSB; high half always zero) + * data[2] = key_store_size + * The address is set unconditionally via set_phy_addr_to_words() and + * its length is the full u32 key_store_size. + */ + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 2, .size_mask = 0xFFFFFFFFu }, /* key_store_address */ +}; + +const struct se_cmd_addr_field *ele_fw_cmd_addr_fields(u8 cmd, size_t *count) +{ + switch (cmd) { + case ELE_PUB_KEY_EXPORT_REQ: + *count = ARRAY_SIZE(ele_pub_key_export_addr_fields); + return ele_pub_key_export_addr_fields; + case ELE_KEYSTORE_REPROV_ENABLE_REQ: + *count = ARRAY_SIZE(ele_keystore_reprov_en_addr_fields); + return ele_keystore_reprov_en_addr_fields; + case ELE_KEYGEN_REQ: + *count = ARRAY_SIZE(ele_keygen_addr_fields); + return ele_keygen_addr_fields; + case ELE_KEY_EXCHANGE_REQ: + *count = ARRAY_SIZE(ele_key_exchange_addr_fields); + return ele_key_exchange_addr_fields; + case ELE_KEY_IMPORT_REQ: + *count = ARRAY_SIZE(ele_key_import_addr_fields); + return ele_key_import_addr_fields; + case ELE_MAC_REQ: + *count = ARRAY_SIZE(ele_mac_addr_fields); + return ele_mac_addr_fields; + case ELE_CIPHER_REQ: + *count = ARRAY_SIZE(ele_cipher_addr_fields); + return ele_cipher_addr_fields; + case ELE_AUTH_ENC_REQ: + *count = ARRAY_SIZE(ele_auth_enc_addr_fields); + return ele_auth_enc_addr_fields; + case ELE_AUTH_ENC_NEW_REQ: + *count = ARRAY_SIZE(ele_auth_enc_new_addr_fields); + return ele_auth_enc_new_addr_fields; + case ELE_SIGNATURE_GENERATE_REQ: + *count = ARRAY_SIZE(ele_sign_gen_addr_fields); + return ele_sign_gen_addr_fields; + case ELE_PUB_KEY_ATTEST_REQ: + *count = ARRAY_SIZE(ele_pub_key_attest_addr_fields); + return ele_pub_key_attest_addr_fields; + case ELE_SIGNATURE_VERIFY_REQ: + *count = ARRAY_SIZE(ele_verify_sign_addr_fields); + return ele_verify_sign_addr_fields; + case ELE_DATA_STORAGE_REQ: + *count = ARRAY_SIZE(ele_data_storage_addr_fields); + return ele_data_storage_addr_fields; + case ELE_ENC_DATA_STORAGE_REQ: + *count = ARRAY_SIZE(ele_enc_data_storage_addr_fields); + return ele_enc_data_storage_addr_fields; + case ELE_ASYMMETRIC_ENC_REQ: + *count = ARRAY_SIZE(ele_asym_enc_addr_fields); + return ele_asym_enc_addr_fields; + case ELE_KEY_GENERIC_CRYPTO_REQ: + *count = ARRAY_SIZE(ele_key_generic_crypto_addr_fields); + return ele_key_generic_crypto_addr_fields; + case ELE_GC_CIPHER_REQ: + *count = ARRAY_SIZE(ele_gc_cipher_addr_fields); + return ele_gc_cipher_addr_fields; + case ELE_GC_AEAD_REQ: + *count = ARRAY_SIZE(ele_gc_aead_addr_fields); + return ele_gc_aead_addr_fields; + case ELE_GC_ACRYPTO_REQ: + *count = ARRAY_SIZE(ele_gc_acrypto_addr_fields); + return ele_gc_acrypto_addr_fields; + case ELE_GC_AKEY_GEN_REQ: + *count = ARRAY_SIZE(ele_gc_akey_gen_addr_fields); + return ele_gc_akey_gen_addr_fields; + case ELE_HASH_ONE_GO_REQ: + *count = ARRAY_SIZE(ele_hash_one_go_addr_fields); + return ele_hash_one_go_addr_fields; + case ELE_RNG_GET_RANDOM_REQ: + *count = ARRAY_SIZE(ele_rng_get_random_addr_fields); + return ele_rng_get_random_addr_fields; + case ELE_STORAGE_MASTER_IMPORT_REQ: + *count = ARRAY_SIZE(ele_storage_master_import_addr_fields); + return ele_storage_master_import_addr_fields; + default: + *count = 0; + return NULL; + } +} + +/* + * FW API for Command Receiver. + * + * Storage master-export response (ELE_STORAGE_MASTER_EXPORT_REQ). + * The cmd_receiver sends this response to firmware to supply the + * output buffer address. Payload layout: + * data[0] = storage_handle + * data[1] = rsp_code + * data[2] = key_store_export_address (LSB; high half always zero) + * No length word is present in the response itself; the export size is + * taken from the FW command received earlier (key_store_size) and stored + * in se_if_priv.cmd_rcvr_var_size by cmd_receiver_specific_ops(). + * se_val_cmd_addrs() reads it when size_idx == SE_CMD_RCVR_ADDR_VAR_SIZE + * to range-check the full response buffer before it is forwarded to FW. + */ +static const struct se_cmd_addr_field ele_storage_master_export_addr_fields[] = { + { .lsb_idx = 2, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = SE_CMD_RCVR_ADDR_VAR_SIZE }, /* key_store_export_address */ +}; + +/* + * Storage chunk-get response (ELE_STORAGE_CHUNK_GET_REQ). + * The cmd_receiver fills in the chunk buffer address and its size so + * firmware can DMA the chunk data into the kernel's coherent buffer. + * Payload layout: + * data[0] = chunk_size + * data[1] = chunk_addr (LSB; high half always zero) + * data[2] = rsp_code + * The size word precedes the address in the message. + */ +static const struct se_cmd_addr_field ele_storage_chunk_get_addr_fields[] = { + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = 0, .size_mask = 0xFFFFFFFFu }, /* chunk_addr */ +}; + +/* + * Storage chunk-export response (ELE_STORAGE_CHUNK_EXPORT_REQ). + * The cmd_receiver supplies the output buffer address. Payload layout: + * data[0] = rsp_code + * data[1] = chunk_export_address (LSB; high half always zero) + * No length word is present in the response itself; the export size is + * taken from the FW command received earlier (chunk_size) and stored + * in se_if_priv.cmd_rcvr_var_size by cmd_receiver_specific_ops(). + * se_val_cmd_addrs() reads it when size_idx == SE_CMD_RCVR_ADDR_VAR_SIZE + * to range-check the full response buffer before it is forwarded to FW. + */ +static const struct se_cmd_addr_field ele_storage_chunk_export_addr_fields[] = { + { .lsb_idx = 1, .flag_idx = SE_CMD_ADDR_ALWAYS, + .size_idx = SE_CMD_RCVR_ADDR_VAR_SIZE }, /* chunk_export_address */ +}; + +/* + * Return the address-field descriptor table for a cmd_receiver response + * message (rsp_tag), or NULL when the response embeds no DMA addresses. + * count is set to the number of entries. Only the three storage responses + * that supply a kernel buffer address to firmware are covered here; + * ELE_STORAGE_EXPORT_FINISH_REQ, ELE_STORAGE_CHUNK_GET_DONE_REQ, and + * ELE_STORAGE_CHUNK_DELETE_REQ carry no DMA addresses and return NULL. + */ +const struct se_cmd_addr_field *ele_fw_rsp_addr_fields(u8 cmd, size_t *count) +{ + switch (cmd) { + case ELE_STORAGE_MASTER_EXPORT_REQ: + *count = ARRAY_SIZE(ele_storage_master_export_addr_fields); + return ele_storage_master_export_addr_fields; + case ELE_STORAGE_CHUNK_GET_REQ: + *count = ARRAY_SIZE(ele_storage_chunk_get_addr_fields); + return ele_storage_chunk_get_addr_fields; + case ELE_STORAGE_CHUNK_EXPORT_REQ: + *count = ARRAY_SIZE(ele_storage_chunk_export_addr_fields); + return ele_storage_chunk_export_addr_fields; + default: + *count = 0; + return NULL; + } +} diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c index b5d3421c0987..519f24d24a85 100644 --- a/drivers/firmware/imx/se_ctrl.c +++ b/drivers/firmware/imx/se_ctrl.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -24,18 +26,17 @@ #include #include #include +#include #include "ele_base_msg.h" #include "ele_common.h" +#include "ele_fw_api.h" #include "se_ctrl.h" -#define MAX_SOC_INFO_DATA_SZ 256 -#define SE_TYPE_STR_DBG "dbg" -#define SE_TYPE_STR_HSM "hsm" - -#define SE_TYPE_ID_DBG 0x1 +/* Maximum response buffer size in bytes for debug-dump replies. */ +#define MAX_ALLOWED_TX_MSG_SZ SZ_4K -#define SE_TYPE_ID_HSM 0x2 +#define MAX_SOC_INFO_DATA_SZ 256 struct se_soc_dev_regn { bool soc_dev_registered; @@ -138,6 +139,13 @@ char *get_se_if_name(u8 se_if_id) return "unknown"; } +static u32 get_se_soc_id(struct se_if_priv *priv) +{ + const struct se_if_node *if_node = device_get_match_data(priv->dev); + + return if_node->se_info->soc_id; +} + static struct se_fw_load_info *get_load_fw_instance(struct se_if_priv *priv) { return &priv->load_fw; @@ -294,15 +302,325 @@ static int get_se_soc_info(struct se_if_priv *priv, const struct se_soc_info *se return 0; } +static int load_firmware(struct se_if_priv *priv, const u8 *se_img_file_to_load) +{ + const struct firmware *fw = NULL; + dma_addr_t se_fw_dma_addr; + u32 se_fw_buf_len; + void *se_fw_buf; + int ret; + + if (!se_img_file_to_load) { + dev_err(priv->dev, "FW image is not provided.\n"); + return -EINVAL; + } + ret = request_firmware(&fw, se_img_file_to_load, priv->dev); + if (ret) + return ret; + + if (fw->size > U32_MAX) { + ret = -EFBIG; + release_firmware(fw); + return ret; + } + dev_info(priv->dev, "loading firmware %s.\n", se_img_file_to_load); + + /* + * Serialize access to priv_dev_ctx shared memory to prevent pos + * corruption if two driver-internal callers run concurrently (e.g. + * ele_get_info() racing with load_firmware()). + */ + scoped_guard(mutex, &priv->priv_dev_ctx->fops_lock) { + se_fw_buf_len = fw->size; + ret = get_shared_mem_slot(priv->priv_dev_ctx, + &se_fw_buf_len, &se_fw_dma_addr, + &se_fw_buf); + if (ret) { + dev_err(priv->dev, "Failed to allocate firmware shared buffer: %d\n", + ret); + release_firmware(fw); + return ret; + } + + memcpy(se_fw_buf, fw->data, fw->size); + ret = ele_fw_authenticate(priv, se_fw_dma_addr, se_fw_dma_addr); + if (ret < 0) { + dev_err(priv->dev, + "Error %pe: Authenticate & load SE firmware %s.", + ERR_PTR(ret), se_img_file_to_load); + ret = -EPERM; + } + if (!se_is_fw_busy_ctx(priv->priv_dev_ctx)) + se_dev_ctx_shared_mem_cleanup(priv->priv_dev_ctx); + } + + release_firmware(fw); + + return ret; +} + +static int se_load_firmware(struct se_if_priv *priv) +{ + struct se_fw_load_info *load_fw = get_load_fw_instance(priv); + int ret = 0; + + guard(mutex)(&load_fw->load_fw_lock); + if (!load_fw->is_fw_tobe_loaded) + return 0; + + if (load_fw->imem.state == ELE_IMEM_STATE_BAD) { + ret = load_firmware(priv, load_fw->se_fw_img_nm->prim_fw_nm_in_rfs); + if (ret) { + dev_err(priv->dev, "Failed to load boot firmware.\n"); + return -EPERM; + } + } + + ret = load_firmware(priv, load_fw->se_fw_img_nm->seco_fw_nm_in_rfs); + if (ret) { + dev_err(priv->dev, "Failed to load runtime firmware.\n"); + return -EPERM; + } + + load_fw->is_fw_tobe_loaded = false; + + return ret; +} + +static int init_se_shared_mem(struct se_if_device_ctx *dev_ctx) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct se_if_priv *priv = dev_ctx->priv; + + INIT_LIST_HEAD(&se_shared_mem_mgmt->pending_out); + INIT_LIST_HEAD(&se_shared_mem_mgmt->pending_in); + + if (priv->mem_pool) + INIT_LIST_HEAD(&se_shared_mem_mgmt->mem_pool_buf_list); + + se_shared_mem_mgmt->non_secure_mem.ptr = + dma_alloc_coherent(priv->dev, MAX_DATA_SIZE_PER_USER, + &se_shared_mem_mgmt->non_secure_mem.dma_addr, + GFP_KERNEL); + if (!se_shared_mem_mgmt->non_secure_mem.ptr) + return -ENOMEM; + + se_shared_mem_mgmt->non_secure_mem.size = MAX_DATA_SIZE_PER_USER; + se_shared_mem_mgmt->non_secure_mem.pos = 0; + + return 0; +} + +static void cleanup_se_shared_mem(struct se_if_device_ctx *dev_ctx, bool reclaim) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct se_if_priv *priv = dev_ctx->priv; + bool free_dma_buf; + + /* + * mem_pool_buf_list is only initialised for interfaces that own a + * gen_pool (priv->mem_pool != NULL). On interfaces without a pool + * (e.g. imx93, which has no pool_name) the list head is left + * zero-filled, so se_cleanup_mem_pool_buf() must not walk it here or + * list_for_each_entry_safe() would dereference a NULL head and panic + * the kernel on close/teardown. Skip the pool cleanup entirely when + * there is no pool; there is nothing to reclaim in that case. + */ + if (priv->mem_pool) + se_cleanup_mem_pool_buf(dev_ctx, reclaim); + + /* Guard against being called before shared memory was ever allocated + * (e.g. probe failure before dma_alloc_coherent succeeded). + */ + if (!se_shared_mem_mgmt->non_secure_mem.ptr) + return; + + /* + * Decide whether the DMA buffer can be released before touching the + * pending lists. se_dev_ctx_shared_mem_cleanup() resets + * non_secure_mem.pos, so the "nothing staged" test must be sampled + * here first. When reclaim is false the buffer is released only if no + * data is still staged for the firmware; otherwise the enclave may + * still be DMA-ing into it and the buffer is deliberately leaked to + * avoid a DMA-after-free. + */ + free_dma_buf = reclaim || !se_shared_mem_mgmt->non_secure_mem.pos; + + /* + * Free any se_buf_desc items that were never consumed (e.g. when the + * fd is closed while pending I/O buffers are still listed). This must + * happen before the DMA backing memory is released to avoid a leak. + */ + se_dev_ctx_shared_mem_cleanup(dev_ctx); + + if (free_dma_buf) { + dma_free_coherent(priv->dev, MAX_DATA_SIZE_PER_USER, + se_shared_mem_mgmt->non_secure_mem.ptr, + se_shared_mem_mgmt->non_secure_mem.dma_addr); + } + + /* + * Drop the host-side tracking unconditionally. On the reclaim path the + * buffer has been freed. On the deliberate-leak path the buffer is + * abandoned on purpose, so clearing the pointer here guarantees a later + * cleanup pass (e.g. se_if_priv_release()) cannot double-free it. + */ + se_shared_mem_mgmt->non_secure_mem.ptr = NULL; + se_shared_mem_mgmt->non_secure_mem.dma_addr = 0; + se_shared_mem_mgmt->non_secure_mem.size = 0; + se_shared_mem_mgmt->non_secure_mem.pos = 0; +} + +static int se_dev_ctx_cpy_out_data(struct se_if_device_ctx *dev_ctx) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct se_if_priv *priv = dev_ctx->priv; + struct se_buf_desc *b_desc, *temp; + bool do_cpy = true; + + list_for_each_entry_safe(b_desc, temp, &se_shared_mem_mgmt->pending_out, link) { + if (b_desc->usr_buf_ptr && b_desc->shared_buf_ptr && do_cpy) { + dev_dbg(priv->dev, "Copying output data to user.\n"); + if (do_cpy && copy_to_user(b_desc->usr_buf_ptr, + b_desc->shared_buf_ptr, + b_desc->size)) { + dev_err(priv->dev, "Failure copying output data to user.\n"); + do_cpy = false; + } + } + + if (b_desc->shared_buf_ptr) + memset(b_desc->shared_buf_ptr, 0, b_desc->size); + + list_del(&b_desc->link); + kfree(b_desc); + } + + return do_cpy ? 0 : -EFAULT; +} + +/* + * Clean the used Shared Memory space, + * whether its Input Data copied from user buffers, or + * Data received from FW. + */ +void se_dev_ctx_shared_mem_cleanup(struct se_if_device_ctx *dev_ctx) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct list_head *pending_lists[] = {&se_shared_mem_mgmt->pending_in, + &se_shared_mem_mgmt->pending_out}; + struct se_buf_desc *b_desc, *temp; + bool is_fw_busy_dev_ctx; + int i; + + /* + * If this context is the one that caused a firmware timeout the shared + * DMA buffers may still be actively read/written by the firmware. + */ + is_fw_busy_dev_ctx = se_is_fw_busy_ctx(dev_ctx); + + for (i = 0; i < ARRAY_SIZE(pending_lists); i++) { + list_for_each_entry_safe(b_desc, temp, pending_lists[i], link) { + if (!is_fw_busy_dev_ctx && b_desc->shared_buf_ptr) + memset(b_desc->shared_buf_ptr, 0, b_desc->size); + + list_del(&b_desc->link); + kfree(b_desc); + } + } + + /* + * Keep non_secure_mem.pos non-zero while this context still owns an + * outstanding firmware transaction. A non-zero pos is the marker that + * data is still staged for the enclave, which cleanup_se_shared_mem() + * uses to decide the buffer must be leaked rather than freed. Resetting + * it here would let a later teardown pass free a buffer the enclave may + * still be DMA-ing into. + */ + if (!is_fw_busy_dev_ctx) + se_shared_mem_mgmt->non_secure_mem.pos = 0; +} + +static struct se_buf_desc *add_b_desc_to_pending_list(void *shared_ptr_with_pos, + struct se_ioctl_setup_iobuf *io, + struct se_if_device_ctx *dev_ctx) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct se_buf_desc *b_desc = NULL; + + b_desc = kzalloc_obj(*b_desc); + if (!b_desc) + return ERR_PTR(-ENOMEM); + + b_desc->shared_buf_ptr = shared_ptr_with_pos; + b_desc->usr_buf_ptr = u64_to_user_ptr(io->user_buf); + b_desc->size = io->length; + + if (io->flags & SE_IO_BUF_FLAGS_IS_INPUT) { + /* + * buffer is input: + * add an entry in the "pending input buffers" list so + * that copied data can be cleaned from shared memory + * later. + */ + list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_in); + } else { + /* + * buffer is output: + * add an entry in the "pending out buffers" list so data + * can be copied to user space when receiving Secure-Enclave + * response. + */ + list_add_tail(&b_desc->link, &se_shared_mem_mgmt->pending_out); + } + + return b_desc; +} + +static void se_if_open_gate_release(struct kref *kref) +{ + struct se_if_open_gate *gate = + container_of(kref, struct se_if_open_gate, refcount); + + kfree(gate); +} + +static bool se_if_open_gate_get(struct se_if_open_gate *gate) +{ + if (!gate) + return false; + + return kref_get_unless_zero(&gate->refcount); +} + +static void se_if_open_gate_put(struct se_if_open_gate *gate) +{ + if (gate) + kref_put(&gate->refcount, se_if_open_gate_release); +} + +/* + * Distinct lockdep class for the internal priv_dev_ctx fops_lock. Taking it + * while an open context's fops_lock is held (for example a firmware load + * triggered from an ioctl) is valid hierarchical locking, but shares the same + * class as the per-open fops_lock and would otherwise be misreported as + * recursive locking by lockdep. + */ +static struct lock_class_key se_priv_ctx_fops_key; + static int init_misc_device_context(struct se_if_priv *priv, int ch_id, - struct se_if_device_ctx **new_dev_ctx) + struct se_if_device_ctx **new_dev_ctx, + const struct file_operations *se_if_fops) { + struct se_if_open_gate *gate = NULL; struct se_if_device_ctx *dev_ctx; + int ret = -ENOMEM; dev_ctx = kzalloc_obj(*dev_ctx); if (!dev_ctx) return -ENOMEM; + dev_ctx->priv = priv; dev_ctx->devname = kasprintf(GFP_KERNEL, "%s0_ch%d", get_se_if_name(priv->if_defs->se_if_type), ch_id); @@ -311,10 +629,53 @@ static int init_misc_device_context(struct se_if_priv *priv, int ch_id, return -ENOMEM; } - dev_ctx->priv = priv; + mutex_init(&dev_ctx->fops_lock); + lockdep_set_class(&dev_ctx->fops_lock, &se_priv_ctx_fops_key); + + kref_init(&dev_ctx->refcount); + dev_ctx->cleanup_done = false; *new_dev_ctx = dev_ctx; + set_se_rcv_msg_timeout(dev_ctx, SE_RCV_MSG_DEFAULT_TIMEOUT_MS); + + ret = init_se_shared_mem(dev_ctx); + if (ret < 0) + goto exit; + + gate = kzalloc_obj(*gate); + if (!gate) { + ret = -ENOMEM; + goto exit; + } + + mutex_init(&gate->lock); + kref_init(&gate->refcount); /* device-owned reference */ + gate->priv = priv; + gate->dying = false; + priv->open_gate = gate; + + /* + * The miscdevice storage is now owned by the open gate object. + * priv->priv_dev_ctx still keeps a pointer to that miscdevice. + */ + dev_ctx->miscdev = &gate->miscdev; + + dev_ctx->miscdev->name = dev_ctx->devname; + dev_ctx->miscdev->minor = MISC_DYNAMIC_MINOR; + dev_ctx->miscdev->fops = se_if_fops; + dev_ctx->miscdev->parent = priv->dev; return 0; +exit: + *new_dev_ctx = NULL; + + if (gate) { + priv->open_gate = NULL; + se_if_open_gate_put(gate); + } + cleanup_se_shared_mem(dev_ctx, true); + kfree(dev_ctx->devname); + kfree(dev_ctx); + return ret; } static int se_if_request_channel(struct device *dev, struct mbox_chan **chan, @@ -332,43 +693,236 @@ static int se_if_request_channel(struct device *dev, struct mbox_chan **chan, return 0; } +/* + * Forward declarations. se_if_probe_cleanup() and se_if_probe() are kept + * together as the teardown/probe pair, but several helpers, the file + * operations table and the firmware-busy work handler they reference are + * defined further down in this file. + */ +static void dlink_dev_ctx(struct se_if_device_ctx *dev_ctx); +static void cleanup_dev_ctx(struct se_if_device_ctx *dev_ctx, bool is_fclose); +static void se_clear_fw_busy(struct se_if_priv *priv); +static void se_if_dev_ctx_release(struct kref *kref); +static void se_if_priv_release(struct kref *kref); +static int se_if_misc_register(struct se_if_priv *priv); +static void se_fw_busy_work(struct work_struct *work); +static const struct file_operations se_if_fops; + static void se_if_probe_cleanup(void *plat_dev) { struct platform_device *pdev = plat_dev; + struct se_if_device_ctx *dev_ctx; struct device *dev = &pdev->dev; + struct fw_busy_info *fbusy_info; struct se_if_priv *priv; priv = dev_get_drvdata(dev); if (!priv) return; - if (priv->rx_chan) - mbox_free_channel(priv->rx_chan); - if (priv->tx_chan) - mbox_free_channel(priv->tx_chan); + fbusy_info = &priv->fw_busy_info; /* - * Being device managed buffer, no need to free the buffer allocated - * in se probe to store encrypted IMEM. + * Announce teardown, then wake any in-flight waiter. going_away makes + * ele_msg_send_rcv() bail out instead of arming a new transaction and + * lets ele_msg_rcv() tell a teardown-forced completion apart from a + * real response; it must be set before complete_all(). + * + * Set it under clbk_rx_lock, not se_if_cmd_lock: se_if_cmd_lock is held + * across the whole blocking transaction, so taking it here would stall + * unbind for a full receive-timeout. clbk_rx_lock is the short spinlock + * ele_msg_send_rcv() holds while arming, so this closes the lost-wakeup + * window - the sender either sees going_away and bails before arming, or + * armed first and this store (and complete_all()) is ordered after its + * reinit_completion() - and supplies the ordering the relaxed atomics do + * not. + */ + scoped_guard(spinlock_irqsave, &priv->waiting_rsp_clbk_hdl.clbk_rx_lock) + atomic_set(&priv->going_away, 1); + /* + * Wake the waiter before iterating the device-context list. It sleeps on + * this completion holding dev_ctx->fops_lock, which cleanup_dev_ctx() + * below also takes, so completing first avoids an unbind hang. Runs + * outside clbk_rx_lock; the going_away store above already orders it + * against the arming path. */ + complete_all(&priv->waiting_rsp_clbk_hdl.done); /* - * No need to check, if reserved memory is allocated - * before calling for its release. Or clearing the - * un-set bit. + * Only now reserve the messaging interface for this teardown flow. + * + * se_reserve_msg_if() blocks on msg_excl_flow_lock, and the fw_busy + * recovery worker (se_fw_busy_work() -> se_clear_fw_busy()) may already + * hold that reservation while parked uninterruptibly in ele_msg_rcv() + * waiting on a possibly hung firmware for up to the full receive + * timeout. The only thing that cuts that wait short is the complete_all() + * above, so it MUST run before this reserve: otherwise teardown would + * sleep on the reservation the worker holds, the worker would stay + * blocked on firmware, and unbind would stall for the entire multi- + * thousand-second timeout (an unbind hang / hung-task). + * + * With going_away already set and the in-flight waiter already forced to + * unwind, the worker returns promptly (its send is failed with -ENODEV), + * drops the reservation, and this call acquires it without waiting on + * anything firmware-related. From here on teardown is the exclusive + * owner: ele_msg_send_rcv() lets only this task's priv_dev_ctx close + * traffic through and rejects every other caller. */ - of_reserved_mem_device_release(dev); + se_reserve_msg_if(priv); - dev_set_drvdata(dev, NULL); + /* + * Mark the private device context as cleanup_done first. + * This prevents new device contexts from being created in open(). + */ + if (priv->priv_dev_ctx) { + /* + * Mark cleanup_done under fops_lock so that se_if_fops_open(), + * which checks cleanup_done while holding fops_lock, cannot + * race past this and add a new device context after teardown. + */ + scoped_guard(mutex, &priv->priv_dev_ctx->fops_lock) + priv->priv_dev_ctx->cleanup_done = true; + + if (priv->open_gate) { + scoped_guard(mutex, &priv->open_gate->lock) { + priv->open_gate->dying = true; + priv->open_gate->priv = NULL; + } + } + + /* + * misc_register() is deferred to the end of probe, so the + * device may have a miscdev set up but never registered if + * probe failed before se_if_misc_register(). Only deregister + * when registration actually succeeded. + */ + if (priv->open_gate && priv->open_gate->registered && + priv->priv_dev_ctx->miscdev) + misc_deregister(priv->priv_dev_ctx->miscdev); + } + + while (true) { + bool list_was_empty = false; + + dev_ctx = NULL; + + scoped_guard(mutex, &priv->modify_lock) { + if (list_empty(&priv->dev_ctx_list)) { + list_was_empty = true; + } else { + dev_ctx = list_first_entry(&priv->dev_ctx_list, + struct se_if_device_ctx, link); + + /* pin this context so close() cannot free it under us */ + kref_get(&dev_ctx->refcount); + dlink_dev_ctx(dev_ctx); + } + } + + if (list_was_empty) + break; + + /* + * Local cleanup outside the global lock avoids ABBA deadlock + * with paths that already take dev_ctx->fops_lock first. + */ + cleanup_dev_ctx(dev_ctx, false); + kref_put(&dev_ctx->refcount, se_if_dev_ctx_release); + } + + se_release_msg_if(priv); + /* + * Release any dev_ctx retained by the firmware-busy circuit breaker. + * A synchronous command that timed out parks its dev_ctx in + * fbusy_info->fw_busy_dev_ctx so that a late firmware response can still be + * routed back. If no such response arrived before teardown, that + * retained reference must be dropped here to avoid a leak. + * se_clear_fw_busy() is safe to call unconditionally: it checks + * fbusy_info->fw_busy_dev_ctx under fw_busy_lock and is a no-op when + * nothing is parked. + */ + se_clear_fw_busy(priv); + + /* + * Free the mailbox channels under se_if_cmd_lock. ele_msg_send_rcv() + * holds se_if_cmd_lock for the full duration of a synchronous + * transaction, including the mbox_send_message() call on priv->tx_chan. + * going_away was set above and complete_all() has already woken any + * in-flight waiter, so any transaction in progress will unwind to + * -ENODEV and release the lock quickly. Acquiring se_if_cmd_lock here + * guarantees no caller is still touching the channels when they are + * freed, and nulling the pointers under the lock prevents any sender + * that races past the going_away check from accessing a freed channel. + */ + scoped_guard(mutex, &priv->se_if_cmd_lock) { + if (priv->rx_chan) { + mbox_free_channel(priv->rx_chan); + priv->rx_chan = NULL; + } + if (priv->tx_chan) { + mbox_free_channel(priv->tx_chan); + priv->tx_chan = NULL; + } + } + + /* + * Cancel any pending fw_busy_work before dropping the initial priv + * reference. going_away was set above, so no new work can be scheduled + * after this point. Canceling here while probe_cleanup still holds its + * own priv reference prevents two races: + * + * 1. UAF: if fw_busy_work has dev_ctx == priv_dev_ctx, letting it run + * past this point while se_if_priv_release() frees priv_dev_ctx + * causes a use-after-free of dev_ctx->fops_lock in se_clear_fw_busy(). + * + * 2. Deadlock: if fw_busy_work drops the last priv reference, + * se_if_dev_ctx_release() -> se_if_priv_release() would call + * cancel_work_sync() from inside the worker, causing the worker to + * wait for its own completion. + * + * Both are avoided by canceling here: probe_cleanup still holds a priv + * reference so the worker cannot invoke se_if_priv_release(), and the + * cancel runs from a non-worker context. + */ + cancel_work_sync(&fbusy_info->fw_busy_work); + /* + * Reclaim priv_dev_ctx shared memory before of_reserved_mem_device_release(): + * cleanup_se_shared_mem() calls dma_free_coherent(), which must run while + * the DMA config is still active. fw_busy_work was canceled above, so no + * concurrent caller holds priv_dev_ctx->fops_lock. + * + * reclaim=true is safe even if FW hung at teardown (command timed out, pos + * still non-zero): the ELE region is no-map/shared-dma-pool, so freeing only + * drops the kernel VA/bitmap while the physical pages stay reserved (no + * DMA-after-free). The next probe also sends ELE_GET_INFO into a fresh + * buffer before accepting commands, so a stale FW write to the old buffer is + * never observed by the new driver instance. + */ if (priv->priv_dev_ctx) { - kfree(priv->priv_dev_ctx->devname); - kfree(priv->priv_dev_ctx); + scoped_guard(mutex, &priv->priv_dev_ctx->fops_lock) + cleanup_se_shared_mem(priv->priv_dev_ctx, true); } - mutex_destroy(&priv->load_fw.load_fw_lock); - mutex_destroy(&priv->se_if_cmd_lock); - kfree(priv); + /* + * Release the reserved DMA memory configuration at unbind time, paired + * with of_reserved_mem_device_init() in se_if_probe(). This must not be + * deferred to se_if_priv_release(): that runs when the last file + * descriptor closes, which may be after a new driver instance has already + * called of_reserved_mem_device_init() on the same struct device. Calling + * the release at that point would corrupt the new instance's DMA setup. + */ + of_reserved_mem_device_release(dev); + + /* + * Being device managed buffer, no need to free the buffer allocated + * in se probe to store encrypted IMEM. + */ + + dev_set_drvdata(dev, NULL); + + /* Drop the initial reference - priv will be freed when last fd closes */ + kref_put(&priv->refcount, se_if_priv_release); } static int se_if_probe(struct platform_device *pdev) @@ -391,16 +945,37 @@ static int se_if_probe(struct platform_device *pdev) return -ENOMEM; priv->dev = dev; + /* + * Pin the parent device for the lifetime of priv. A file descriptor may + * stay open after the device is unbound; close() then still passes + * priv->dev to dma_free_coherent()/dev_warn(). Without this reference + * the struct device could be freed while priv->dev still points at it, + * so the reference is dropped in se_if_priv_release() via put_device(). + */ + get_device(priv->dev); + kref_init(&priv->refcount); priv->if_defs = &if_node->if_defs; dev_set_drvdata(dev, priv); spin_lock_init(&priv->cmd_receiver_clbk_hdl.clbk_rx_lock); spin_lock_init(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock); - atomic_set(&priv->fw_busy, 0); + priv->msg_excl_flow.msg_excl_owner = NULL; + spin_lock_init(&priv->msg_excl_flow.msg_excl_lock); + mutex_init(&priv->msg_excl_flow.msg_excl_flow_lock); + struct fw_busy_info *fbusy_info = &priv->fw_busy_info; + + atomic_set(&fbusy_info->fw_busy, 0); + + spin_lock_init(&fbusy_info->fw_busy_lock); + fbusy_info->fw_busy_dev_ctx = NULL; + INIT_WORK(&fbusy_info->fw_busy_work, se_fw_busy_work); + init_completion(&priv->waiting_rsp_clbk_hdl.done); init_completion(&priv->cmd_receiver_clbk_hdl.done); + INIT_LIST_HEAD(&priv->dev_ctx_list); mutex_init(&priv->se_if_cmd_lock); + mutex_init(&priv->modify_lock); load_fw = get_load_fw_instance(priv); mutex_init(&load_fw->load_fw_lock); @@ -455,7 +1030,7 @@ static int se_if_probe(struct platform_device *pdev) load_fw->imem_mgmt = true; } - ret = init_misc_device_context(priv, 0, &priv->priv_dev_ctx); + ret = init_misc_device_context(priv, 0, &priv->priv_dev_ctx, &se_if_fops); if (ret) return dev_err_probe(dev, ret, "Failed to create device contexts.\n"); @@ -466,12 +1041,1314 @@ static int se_if_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "Failed to fetch SoC Info.\n"); } + /* + * All probe-time initialization is complete; expose the + * interface to userspace last so that an open()/ioctl cannot + * race against a not-yet-initialized device. + */ + ret = se_if_misc_register(priv); + if (ret) + return ret; + dev_info(dev, "i.MX secure-enclave: %s0 interface to firmware, configured.\n", get_se_if_name(priv->if_defs->se_if_type)); return ret; } +/* + * Expose the interface to userspace. Deferred until the end of probe so + * the device node only becomes openable after SoC info has been fetched + * and, on SoCs with IMEM management, the encrypted-IMEM buffer has been + * allocated. This prevents userspace from opening the node and issuing + * commands against a partially initialized interface. + */ +static int se_if_misc_register(struct se_if_priv *priv) +{ + int ret; + + ret = misc_register(priv->priv_dev_ctx->miscdev); + if (ret) + return dev_err_probe(priv->dev, ret, + "Failed to register misc device."); + + priv->open_gate->registered = true; + + return 0; +} + +static void se_if_priv_release(struct kref *kref) +{ + struct se_if_priv *priv = container_of(kref, struct se_if_priv, refcount); + + /* + * Free priv_dev_ctx if it still exists. se_if_priv_release() always + * runs after se_if_probe_cleanup() has completed: the initial kref + * held by probe_cleanup is the last one dropped by probe_cleanup + * itself, so no other kref_put() can reach zero -- and therefore + * trigger se_if_priv_release() -- until probe_cleanup's own + * kref_put() fires. By that time cleanup_se_shared_mem() and + * of_reserved_mem_device_release() have already run in + * probe_cleanup, so only the struct itself and its devname string + * need to be freed here. Calling cleanup_se_shared_mem() again + * would be a use-after-free of already-freed DMA memory. + */ + if (priv->priv_dev_ctx) { + kfree(priv->priv_dev_ctx->devname); + kfree(priv->priv_dev_ctx); + priv->priv_dev_ctx = NULL; + } + /* + * Be defensive: if teardown did not already drop the device-owned + * gate reference for some reason, release it here. + */ + if (priv->open_gate) { + se_if_open_gate_put(priv->open_gate); + priv->open_gate = NULL; + } + + /* + * Drop the reference on priv->dev taken in se_if_probe(). The device was + * pinned so that a file descriptor closed after device unbind can still + * safely pass priv->dev to dma_free_coherent()/dev_warn(). + */ + put_device(priv->dev); + mutex_destroy(&priv->load_fw.load_fw_lock); + mutex_destroy(&priv->modify_lock); + mutex_destroy(&priv->se_if_cmd_lock); + mutex_destroy(&priv->msg_excl_flow.msg_excl_flow_lock); + + /* Free any remaining resources that weren't devm-managed */ + kfree(priv); +} + +static void se_if_dev_ctx_release(struct kref *kref) +{ + struct se_if_device_ctx *dev_ctx = + container_of(kref, struct se_if_device_ctx, refcount); + struct se_if_priv *priv = dev_ctx->priv; + + kfree(dev_ctx); + + /* drop the priv reference owned by this device context */ + kref_put(&priv->refcount, se_if_priv_release); +} + +/* + * se_reserve_msg_if() - reserve the SE messaging interface for the current task. + * + * Blocks on msg_excl_flow_lock until this task owns the reservation, then + * publishes current as msg_excl_owner under msg_excl_lock. While a reservation + * is held, ele_msg_send_rcv() lets only the owning task issue transactions and + * rejects every other caller with -EBUSY. Used by the fw_busy recovery flow in + * se_clear_fw_busy() to drive its teardown-close messages through the otherwise + * closed circuit breaker. + * + * If a second flow tries to reserve while the interface is already reserved, + * it sleeps on msg_excl_flow_lock until the current owner calls + * se_release_msg_if(). Must be called from process/workqueue context (it may + * sleep) and every successful call must be balanced by se_release_msg_if(). + * + * Return: 0 (the reservation is always acquired once this returns). + */ +int se_reserve_msg_if(struct se_if_priv *priv) +{ + unsigned long flags; + + mutex_lock(&priv->msg_excl_flow.msg_excl_flow_lock); + /* + * The mutex guarantees this task is now the sole reserver, so + * msg_excl_owner is either NULL or already current. Publish current + * under msg_excl_lock so the lockless READ_ONCE in ele_msg_send_rcv() + * observes a consistent pointer. + */ + spin_lock_irqsave(&priv->msg_excl_flow.msg_excl_lock, flags); + priv->msg_excl_flow.msg_excl_owner = current; + spin_unlock_irqrestore(&priv->msg_excl_flow.msg_excl_lock, flags); + + return 0; +} + +/* se_release_msg_if() - release a reservation taken by se_reserve_msg_if(). */ +void se_release_msg_if(struct se_if_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->msg_excl_flow.msg_excl_lock, flags); + priv->msg_excl_flow.msg_excl_owner = NULL; + spin_unlock_irqrestore(&priv->msg_excl_flow.msg_excl_lock, flags); + mutex_unlock(&priv->msg_excl_flow.msg_excl_flow_lock); +} + +/* se_clear_fw_busy() - atomically clear fw_busy and reclaim the parked dev_ctx. */ +static void se_clear_fw_busy(struct se_if_priv *priv) +{ + struct fw_busy_info *fbusy_info = &priv->fw_busy_info; + struct se_if_device_ctx *dev_ctx = NULL; + unsigned long flags; + + scoped_guard(spinlock_irqsave, &fbusy_info->fw_busy_lock) { + dev_ctx = fbusy_info->fw_busy_dev_ctx; + fbusy_info->fw_busy_dev_ctx = NULL; + + if (!dev_ctx) { + /* + * No parked context: nothing to recover. Clear fw_busy + * and return without reserving the interface, so the + * no-op path never leaves a dangling recovery + * reservation. The scoped_guard releases fw_busy_lock + * on this return. + */ + atomic_set(&fbusy_info->fw_busy, 0); + return; + } + } + + /* + * A context is parked and its handles must be recovered. Keep + * fw_busy set (breaker stays closed to all third parties) and + * reserve the SE interface exclusively for this recovery flow by + * publishing the current task as msg_excl_owner. ele_msg_send_rcv() + * then lets only this task's teardown-close messages through and + * rejects everyone else with -EBUSY. The reservation is assigned here, + * from outside ele_msg_send_rcv(), and released with se_release_msg_if() + * at the end, after which the interface is available for general + * se_if_cmd_lock message exchange. + * + * The scoped_guard above has already dropped fw_busy_lock before this + * se_reserve_msg_if() call: the reserve helper takes msg_excl_lock, and + * taking it while still holding fw_busy_lock would introduce a new + * fw_busy_lock -> msg_excl_lock nesting. The brief fw_busy == 1 / + * owner == NULL window that this opens is harmless - the breaker is + * fully closed, so every caller (including a would-be re-arm) is + * rejected with -EBUSY. + */ + se_reserve_msg_if(priv); + + scoped_guard(mutex, &dev_ctx->fops_lock) { + /* + * Snapshot any orphaned late FW response. On the teardown + * path se_if_probe_cleanup calls se_clear_fw_busy before + * cancel_work_sync, so fw_busy is still 1 here and a late + * IRQ can write orphan_fw_rx_msg concurrently - take + * clbk_rx_lock. On the workqueue path the IRQ writer has + * already finished; the lock is a no-contention formality. + * Call fw_api_specific_ops() outside the spinlock since it + * may sleep. + */ + u8 late_rx_snap[MAX_ALLOWED_RX_MSG_SZ]; + bool have_snap; + + spin_lock_irqsave(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + have_snap = fbusy_info->orphan_fw_rx_msg[0] != 0; + if (have_snap) { + memcpy(late_rx_snap, fbusy_info->orphan_fw_rx_msg, + sizeof(late_rx_snap)); + memset(fbusy_info->orphan_fw_rx_msg, 0, + sizeof(fbusy_info->orphan_fw_rx_msg)); + } + spin_unlock_irqrestore(&priv->waiting_rsp_clbk_hdl.clbk_rx_lock, flags); + + if (have_snap) { + /* + * FW responded late. DMA staging buffer is no longer + * being written - safe to reclaim. Close any firmware + * resource handle carried in the response. + */ + fw_api_specific_ops(priv->priv_dev_ctx, + (struct se_api_msg *)late_rx_snap, true); + + if (dev_ctx == priv->priv_dev_ctx) { + /* + * Internal context: probe-time static DMA buf; + * se_if_probe_cleanup reclaims it explicitly. + * Just reset logical pos and return gen_pool + * loan buffers for reuse. + */ + if (priv->mem_pool) + se_cleanup_mem_pool_buf(dev_ctx, true); + se_dev_ctx_shared_mem_cleanup(dev_ctx); + } else if (dev_ctx->cleanup_done) { + /* + * Userspace fd already closed while fw_busy was + * armed (e.g. SIGKILL). FW has now responded; + * close deferred handles and free the DMA buf. + * + * cleanup_dev_ctx() already freed dev_ctx->devname + * and set it to NULL, so use the stable snapshot + * captured at arm time (fbusy_info->devname) for + * these diagnostics rather than dev_ctx->devname. + */ + if (dev_ctx->strg_hdl && + se_close_storage(priv->priv_dev_ctx, + dev_ctx->strg_hdl)) + dev_err(priv->dev, + "%s: failed to close deferred storage handle\n", + fbusy_info->devname); + if (dev_ctx->sess_hdl && + se_close_session(priv->priv_dev_ctx, + dev_ctx->sess_hdl)) + dev_err(priv->dev, + "%s: failed to close deferred session handle\n", + fbusy_info->devname); + dev_ctx->strg_hdl = 0; + dev_ctx->sess_hdl = 0; + cleanup_se_shared_mem(dev_ctx, true); + } else { + /* Pure timeout, fd still open: reset pos only. */ + se_dev_ctx_shared_mem_cleanup(dev_ctx); + } + } else { + /* + * have_snap=false only on teardown (FW never responded, + * or teardown beat the late IRQ, which going_away then + * drops). priv_dev_ctx is handled by probe_cleanup's + * single cleanup_se_shared_mem(reclaim=true) after + * cancel_work_sync, so nothing to do here. For a + * userspace dev_ctx (cleanup_done already true), use + * reclaim=false: the pos gate leaks the buffer if FW may + * still be writing, else frees it. reclaim=true would + * also be safe here since the region is no-map. + */ + if (dev_ctx != priv->priv_dev_ctx && dev_ctx->cleanup_done) + cleanup_se_shared_mem(dev_ctx, false); + } + } + + /* + * Recovery flow is done: release the exclusive reservation, then clear + * the breaker. se_release_msg_if() drops msg_excl_owner; the fw_busy + * clear below reopens the interface. Ordering is safe either way: while + * fw_busy is still 1 a third party is rejected regardless of owner, and + * once fw_busy is 0 the owner is no longer consulted. + */ + se_release_msg_if(priv); + + spin_lock_irqsave(&fbusy_info->fw_busy_lock, flags); + atomic_set(&fbusy_info->fw_busy, 0); + spin_unlock_irqrestore(&fbusy_info->fw_busy_lock, flags); + kref_put(&dev_ctx->refcount, se_if_dev_ctx_release); +} + +void unset_dev_ctx_as_command_receiver(struct se_if_device_ctx *dev_ctx) +{ + struct se_if_priv *priv = dev_ctx->priv; + struct se_api_msg *old_rx_msg = NULL; + struct se_clbk_handle *se_clbk_hdl; + unsigned long flags; + + lockdep_assert_held(&priv->modify_lock); + + se_clbk_hdl = &priv->cmd_receiver_clbk_hdl; + + if (se_clbk_hdl->dev_ctx == dev_ctx) { + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + old_rx_msg = se_clbk_hdl->rx_msg; + se_clbk_hdl->dev_ctx = NULL; + se_clbk_hdl->rx_msg = NULL; + se_clbk_hdl->rx_msg_sz = 0; + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + + kfree(old_rx_msg); + complete_all(&se_clbk_hdl->done); + } +} + +/* + * check_cmd_rcvr_status() - check whether dev_ctx can become the command + * receiver or is already become the command receiver. + * + * Returns: + * 0 - dev_ctx is already the registered receiver + * -EBUSY - another context is already the receiver + * -EINVAL - dev_ctx has no storage handle + * -ENXIO - ready to proceed: no receiver set, strg_hdl present + * + * Caller must hold priv->modify_lock. + */ +static int check_cmd_rcvr_status(struct se_if_device_ctx *dev_ctx) +{ + struct se_if_priv *priv = dev_ctx->priv; + struct se_clbk_handle *se_clbk_hdl = &priv->cmd_receiver_clbk_hdl; + + lockdep_assert_held(&priv->modify_lock); + + if (se_clbk_hdl->dev_ctx == dev_ctx) + return 0; + + if (se_clbk_hdl->dev_ctx) + return -EBUSY; + + if (!dev_ctx->strg_hdl) + return -EINVAL; + + /* Reaching here means, with a valid storage handle and command-receiver as NULL, + * either the registration process is to be done or failed. + */ + return -ENXIO; +} + +int set_dev_ctx_as_command_receiver(struct se_if_device_ctx *dev_ctx) +{ + struct se_if_priv *priv = dev_ctx->priv; + struct se_clbk_handle *se_clbk_hdl = &priv->cmd_receiver_clbk_hdl; + struct se_api_msg *new_rx_msg = NULL; + unsigned long flags; + int ret; + + guard(mutex)(&priv->modify_lock); + + /* + * All state checks happen inside modify_lock so the result cannot + * go stale between the check and the arming below. + */ + ret = check_cmd_rcvr_status(dev_ctx); + if (ret != -ENXIO) + return ret; + + if (!se_clbk_hdl->rx_msg) { + new_rx_msg = kzalloc(MAX_NVM_MSG_LEN, GFP_KERNEL); + if (!new_rx_msg) + return -ENOMEM; + } + spin_lock_irqsave(&se_clbk_hdl->clbk_rx_lock, flags); + if (new_rx_msg) + se_clbk_hdl->rx_msg = new_rx_msg; + reinit_completion(&se_clbk_hdl->done); + se_clbk_hdl->rx_msg_sz = MAX_NVM_MSG_LEN; + se_clbk_hdl->dev_ctx = dev_ctx; + dev_ctx->rcv_msg_timeout_jiffies = MAX_SCHEDULE_TIMEOUT; + spin_unlock_irqrestore(&se_clbk_hdl->clbk_rx_lock, flags); + + return 0; +} + +static void dlink_dev_ctx(struct se_if_device_ctx *dev_ctx) +{ + struct se_if_priv *priv = dev_ctx->priv; + + unset_dev_ctx_as_command_receiver(dev_ctx); + + if (!list_empty(&dev_ctx->link)) { + list_del_init(&dev_ctx->link); + priv->active_devctx_count--; + } +} + +bool se_is_fw_busy_ctx(struct se_if_device_ctx *dev_ctx) +{ + struct se_if_priv *priv = dev_ctx->priv; + struct fw_busy_info *fbusy_info = &priv->fw_busy_info; + unsigned long flags; + bool match; + + spin_lock_irqsave(&fbusy_info->fw_busy_lock, flags); + match = fbusy_info->fw_busy_dev_ctx == dev_ctx; + spin_unlock_irqrestore(&fbusy_info->fw_busy_lock, flags); + + return match; +} + +static void cleanup_dev_ctx(struct se_if_device_ctx *dev_ctx, bool is_fclose) +{ + struct fw_busy_info *fbusy_info = &dev_ctx->priv->fw_busy_info; + bool already_done; + + scoped_guard(mutex, &dev_ctx->fops_lock) { + already_done = dev_ctx->cleanup_done; + if (!already_done) { + /* + * Ask FW to drop this context's session and storage so + * the kernel and FW stay in sync. Done here, under this + * context's fops_lock only (not the global modify_lock), + * because both close requests block on a firmware + * round-trip; issuing them while modify_lock was held + * would stall every other context for the FW timeout. + * + * Skip the round-trips once the FW path is marked busy. + * fw_busy is armed when a synchronous transaction times + * out; while it is set ele_msg_send_rcv() rejects further + * commands with -EBUSY without waiting. It is only cleared + * by se_clear_fw_busy(), which during unbind runs once + * after this loop (or earlier from fw_busy_work only if a + * genuine late FW response arrives). On a hung FW no late + * response comes, so the breaker stays set for the rest of + * the loop and the remaining closes would just return + * -EBUSY and log spurious "failed to close" errors. Skip + * them and emit a single warning instead. + */ + if (atomic_read(&fbusy_info->fw_busy)) { + if (dev_ctx->strg_hdl || dev_ctx->sess_hdl) + dev_warn(dev_ctx->priv->dev, + "%s: skipping session/storage close, FW is busy\n", + dev_ctx->devname); + } else { + /* + * Choose which dev_ctx sends the close messages. + * fclose: use the caller's own dev_ctx so a race with + * unbind is rejected with -ENODEV instead of hitting a + * freed tx_chan. Teardown: use priv_dev_ctx; going_away + * is set but the reservation (msg_excl_owner == current) + * lets these closes through while tx_chan is still live. + */ + struct se_if_device_ctx *tx_ctx = is_fclose ? dev_ctx : + dev_ctx->priv->priv_dev_ctx; + + if (dev_ctx->strg_hdl && + se_close_storage(tx_ctx, dev_ctx->strg_hdl)) + dev_err(dev_ctx->priv->dev, "failed to close storage.\n"); + if (dev_ctx->sess_hdl && + se_close_session(tx_ctx, dev_ctx->sess_hdl)) + dev_err(dev_ctx->priv->dev, "failed to close session.\n"); + } + /* + * fw_busy is caused by one timed-out synchronous transaction. + * Only that transaction's dev_ctx may still have coherent + * memory referenced by FW. Do not skip cleanup for unrelated + * contexts while fw_busy is set. + */ + if (se_is_fw_busy_ctx(dev_ctx)) + dev_warn(dev_ctx->priv->dev, + "%s: deferring shared memory cleanup while FW is busy\n", + dev_ctx->devname); + else + cleanup_se_shared_mem(dev_ctx, true); + + kfree(dev_ctx->devname); + dev_ctx->devname = NULL; + dev_ctx->cleanup_done = true; + } + } + + if (is_fclose) + kref_put(&dev_ctx->refcount, se_if_dev_ctx_release); +} + +static void dlink_n_cleanup_dev_ctx(struct se_if_device_ctx *dev_ctx, bool is_fclose) +{ + struct se_if_priv *priv = dev_ctx->priv; + + if (is_fclose) { + scoped_guard(mutex, &priv->modify_lock) + dlink_dev_ctx(dev_ctx); + } + + cleanup_dev_ctx(dev_ctx, is_fclose); +} + +static int init_device_context(struct se_if_priv *priv, int ch_id, + struct se_if_device_ctx **new_dev_ctx) +{ + struct se_if_device_ctx *dev_ctx; + int ret = 0; + + dev_ctx = kzalloc_obj(*dev_ctx); + + if (!dev_ctx) + return -ENOMEM; + + dev_ctx->devname = kasprintf(GFP_KERNEL, "%s0_ch%d", + get_se_if_name(priv->if_defs->se_if_type), + ch_id); + if (!dev_ctx->devname) { + kfree(dev_ctx); + return -ENOMEM; + } + + mutex_init(&dev_ctx->fops_lock); + kref_init(&dev_ctx->refcount); + dev_ctx->priv = priv; + dev_ctx->cleanup_done = false; + INIT_LIST_HEAD(&dev_ctx->link); + set_se_rcv_msg_timeout(dev_ctx, SE_RCV_MSG_LONG_TIMEOUT_MS); + *new_dev_ctx = dev_ctx; + + ret = init_se_shared_mem(dev_ctx); + if (ret < 0) { + kfree(dev_ctx->devname); + kfree(dev_ctx); + *new_dev_ctx = NULL; + + return ret; + } + + /* Take a reference to priv for this device context */ + kref_get(&priv->refcount); + + scoped_guard(mutex, &priv->modify_lock) { + list_add_tail(&dev_ctx->link, &priv->dev_ctx_list); + priv->active_devctx_count++; + } + + return ret; +} + +static int se_ioctl_cmd_snd_rcv_cleanup(struct se_if_device_ctx *dev_ctx, void __user *uarg, + struct se_ioctl_cmd_snd_rcv_rsp_info *cmd_snd_rcv_rsp_info) +{ + /* shared memory is allocated before this IOCTL */ + se_dev_ctx_shared_mem_cleanup(dev_ctx); + + if (cmd_snd_rcv_rsp_info->rx_buf_sz && + copy_to_user(uarg, cmd_snd_rcv_rsp_info, sizeof(*cmd_snd_rcv_rsp_info))) { + dev_err(dev_ctx->priv->dev, "%s: Failed to copy cmd_snd_rcv_rsp_info to user.\n", + dev_ctx->devname); + return -EFAULT; + } + + return 0; +} + +static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx, + void __user *uarg) +{ + struct se_ioctl_cmd_snd_rcv_rsp_info cmd_snd_rcv_rsp_info = {0}; + struct se_if_priv *priv = dev_ctx->priv; + int rsp_status_err = 0; + int act_rx_msg_sz = 0; + int cleanup_err = 0; + int err = 0; + + if (copy_from_user(&cmd_snd_rcv_rsp_info, uarg, + sizeof(cmd_snd_rcv_rsp_info))) { + dev_err(priv->dev, + "%s: Failed to copy cmd_snd_rcv_rsp_info from user.", + dev_ctx->devname); + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return -EFAULT; + } + + if (cmd_snd_rcv_rsp_info.tx_buf_sz < SE_MU_HDR_SZ || + cmd_snd_rcv_rsp_info.tx_buf_sz > MAX_ALLOWED_TX_MSG_SZ) { + dev_err(priv->dev, "%s: User buffer too small/large(%d < %d)\n", + dev_ctx->devname, cmd_snd_rcv_rsp_info.tx_buf_sz, + cmd_snd_rcv_rsp_info.tx_buf_sz < SE_MU_HDR_SZ ? SE_MU_HDR_SZ : + MAX_ALLOWED_TX_MSG_SZ); + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return -ENOSPC; + } + + struct se_api_msg *tx_msg __free(kfree) = + memdup_user(u64_to_user_ptr(cmd_snd_rcv_rsp_info.tx_buf), + cmd_snd_rcv_rsp_info.tx_buf_sz); + if (IS_ERR(tx_msg)) { + err = PTR_ERR(tx_msg); + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return err; + } + + err = se_chk_tx_cmd_msg_hdr(dev_ctx, &tx_msg->header, + cmd_snd_rcv_rsp_info.tx_buf_sz, + cmd_snd_rcv_rsp_info.rx_buf_sz); + if (err) { + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return err; + } + + if (cmd_snd_rcv_rsp_info.rx_buf_sz < SE_MU_HDR_SZ || + cmd_snd_rcv_rsp_info.rx_buf_sz > MAX_ALLOWED_RX_MSG_SZ) { + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return -EINVAL; + } + + if (tx_msg->header.tag != priv->if_defs->cmd_tag) { + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return -EINVAL; + } + + if (tx_msg->header.ver == priv->if_defs->fw_api_ver && + get_load_fw_instance(priv)->is_fw_tobe_loaded) { + err = se_load_firmware(priv); + if (err) { + dev_err(priv->dev, "Could not send msg as FW is not loaded.\n"); + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return -EPERM; + } + } + + struct se_api_msg *rx_msg __free(kfree) = + kzalloc(cmd_snd_rcv_rsp_info.rx_buf_sz, GFP_KERNEL); + if (!rx_msg) { + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return -ENOMEM; + } + + err = ele_msg_send_rcv(dev_ctx, tx_msg, cmd_snd_rcv_rsp_info.tx_buf_sz, + rx_msg, cmd_snd_rcv_rsp_info.rx_buf_sz, &act_rx_msg_sz); + if (err < 0) { + /* + * -ERESTARTSYS here means the wait was interrupted by a signal + * after the command had already been handed to - and executed + * by - the firmware, with its response delivered into rx_msg + * (ele_msg_send_rcv() converts only a positive, i.e. successfully + * received, result to -ERESTARTSYS). If that response carried a + * freshly allocated session/storage handle, record it now via + * fw_api_specific_ops(): the handle is already live in firmware, + * so leaving it untracked would stop cleanup_dev_ctx() from ever + * closing it and leak the firmware resource. Validate the + * delivered response first, using its own declared length bounded + * by the caller's buffer, so a truncated or malformed reply is + * not acted upon. + */ + if (err == -ERESTARTSYS) { + u32 rsp_sz = rx_msg->header.size << 2; + + if (rsp_sz && rsp_sz <= cmd_snd_rcv_rsp_info.rx_buf_sz && + !se_val_rsp_hdr_n_status(dev_ctx, rx_msg, + tx_msg->header.command, act_rx_msg_sz, + tx_msg->header.ver)) { + se_dev_ctx_cpy_out_data(dev_ctx); + fw_api_specific_ops(dev_ctx, rx_msg, true); + } + /* + * NOTE: se_dev_ctx_cpy_out_data() above has already + * copied the firmware response payload to userspace before + * this point. Returning -EINTR here is intentional, not + * -ERESTARTSYS: the VFS would transparently restart the + * ioctl on -ERESTARTSYS, re-issuing the command with + * already-zeroed shared input buffers. -EINTR prevents + * auto-restart and lets userspace enter its signal handler + * to decide whether to reissue the command. + * See Documentation/driver-api/firmware/other_interfaces.rst, + * section "Signal handling after a completed hardware + * operation". + */ + err = -EINTR; + } + + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + + return err; + } + + /* + * ele_msg_send_rcv() returns a positive received-message size on + * success. Returning that raw size as the ioctl result would make a + * successful transaction look like a positive (non-zero) return value + * to userspace. Record the actual received size in rx_buf_sz for the + * response copied back to userspace, then normalise err to 0 so the + * ioctl reports plain success; the firmware status is conveyed to + * userspace inside the response buffer itself. + */ + cmd_snd_rcv_rsp_info.rx_buf_sz = act_rx_msg_sz; + err = 0; + + dev_dbg(priv->dev, "%s: %s %s.\n", dev_ctx->devname, __func__, + "message received, start transmit to user"); + + rsp_status_err = + se_val_rsp_hdr_n_status(dev_ctx, rx_msg, tx_msg->header.command, + act_rx_msg_sz, tx_msg->header.ver); + + if (!rsp_status_err) { + /* + * For msg IDs handled by fw_api_specific_ops(), the exact + * response size was already ensured in ele_uapi_allowed_fw_cmd(). + */ + err = fw_api_specific_ops(dev_ctx, rx_msg, false); + if (err) { + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return err; + } + + err = se_dev_ctx_cpy_out_data(dev_ctx); + if (err < 0) { + se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + return err; + } + } + + /* Copy data from the buffer */ + print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4, rx_msg, + cmd_snd_rcv_rsp_info.rx_buf_sz, false); + + if (copy_to_user(u64_to_user_ptr(cmd_snd_rcv_rsp_info.rx_buf), rx_msg, + cmd_snd_rcv_rsp_info.rx_buf_sz)) { + dev_err(priv->dev, "%s: Failed to copy to user.\n", dev_ctx->devname); + err = -EFAULT; + } + + cleanup_err = se_ioctl_cmd_snd_rcv_cleanup(dev_ctx, uarg, &cmd_snd_rcv_rsp_info); + + if (cleanup_err && !err) + err = cleanup_err; + + return err; +} + +static int se_ioctl_get_mu_info(struct se_if_device_ctx *dev_ctx, + void __user *uarg) +{ + struct se_if_priv *priv = dev_ctx->priv; + struct se_ioctl_get_if_info if_info; + struct se_if_node *if_node; + int err = 0; + + if_node = container_of(priv->if_defs, typeof(*if_node), if_defs); + + if_info.se_if_id = 0; + if_info.interrupt_idx = 0; + if_info.tz = 0; + if_info.did = 0; + if_info.cmd_tag = priv->if_defs->cmd_tag; + if_info.rsp_tag = priv->if_defs->rsp_tag; + if_info.success_tag = priv->if_defs->success_tag; + if_info.base_api_ver = priv->if_defs->base_api_ver; + if_info.fw_api_ver = priv->if_defs->fw_api_ver; + + dev_dbg(priv->dev, "%s: info [se_if_id: %d, irq_idx: %d, tz: 0x%x, did: 0x%x].\n", + dev_ctx->devname, if_info.se_if_id, if_info.interrupt_idx, if_info.tz, + if_info.did); + + if (copy_to_user(uarg, &if_info, sizeof(if_info))) { + dev_err(priv->dev, "%s: Failed to copy mu info to user.\n", + dev_ctx->devname); + err = -EFAULT; + } + + return err; +} + +static void rollback_shared_mem_pos(struct se_if_device_ctx *dev_ctx, u32 length) +{ + struct se_shared_mem *shared_mem = NULL; + + shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem; + + if (WARN_ON_ONCE(length > shared_mem->pos)) { + shared_mem->pos = 0; + return; + } + + shared_mem->pos -= length; +} + +int get_shared_mem_slot(struct se_if_device_ctx *dev_ctx, + u32 *length, dma_addr_t *ele_dma_addr, void **ptr) +{ + struct se_shared_mem *shared_mem = NULL; + bool is_fw_busy_dev_ctx; + size_t aligned_len = 0; + u32 pos; + + /* + * If this context is the one that caused a firmware timeout the shared + * DMA buffers may still be actively read/written by the firmware. + */ + is_fw_busy_dev_ctx = se_is_fw_busy_ctx(dev_ctx); + if (is_fw_busy_dev_ctx) + return -EBUSY; + + aligned_len = round_up((size_t)*length, 8); + if (aligned_len < *length) { + dev_err(dev_ctx->priv->dev, "%s: Invalid buffer length.\n", + dev_ctx->devname); + return -EINVAL; + } + + /* No specific requirement for this buffer. */ + shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem; + + /* Check there is enough space in the shared memory. */ + dev_dbg(dev_ctx->priv->dev, "%s: req_size = %zd, max_size= %d, curr_pos = %d\n", + dev_ctx->devname, aligned_len, shared_mem->size, + shared_mem->pos); + + if (shared_mem->size < shared_mem->pos || + aligned_len > (shared_mem->size - shared_mem->pos)) { + dev_err(dev_ctx->priv->dev, "%s: Not enough space in shared memory.\n", + dev_ctx->devname); + return -ENOMEM; + } + + /* Allocate space in shared memory. 8 bytes aligned. */ + pos = shared_mem->pos; + shared_mem->pos += aligned_len; + *ele_dma_addr = (u64)shared_mem->dma_addr + pos; + *ptr = shared_mem->ptr + pos; + *length = aligned_len; + + memset(shared_mem->ptr + pos, 0, aligned_len); + + return 0; +} + +/* + * Copy a buffer of data to/from the user and return the address to use in + * messages + */ +static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx, + void __user *uarg) +{ + struct se_ioctl_setup_iobuf io = {0}; + struct se_buf_desc *b_desc = NULL; + void *dma_buf_ptr = NULL; + dma_addr_t ele_dma_addr; + u32 aligned_len = 0; + int err = 0; + + if (copy_from_user(&io, uarg, sizeof(io))) { + dev_err(dev_ctx->priv->dev, "%s: Failed copy iobuf config from user.\n", + dev_ctx->devname); + return -EFAULT; + } + + dev_dbg(dev_ctx->priv->dev, "%s: io [buf: %p(%d) flag: %x].\n", dev_ctx->devname, + u64_to_user_ptr(io.user_buf), io.length, io.flags); + + if (io.length == 0 || !io.user_buf) { + /* + * Accept NULL pointers since some buffers are optional + * in FW commands. In this case we should return 0 as + * pointer to be embedded into the message. + * Skip all data copy part of code below. + */ + io.ele_addr = 0; + goto copy; + } + + aligned_len = io.length; + err = get_shared_mem_slot(dev_ctx, &aligned_len, &ele_dma_addr, &dma_buf_ptr); + if (err) + return err; + + io.ele_addr = ele_dma_addr; + if ((io.flags & SE_IO_BUF_FLAGS_IS_INPUT) || + (io.flags & SE_IO_BUF_FLAGS_IS_IN_OUT)) { + /* + * buffer is input: + * copy data from user space to this allocated buffer. + */ + if (copy_from_user(dma_buf_ptr, u64_to_user_ptr(io.user_buf), + io.length)) { + dev_err(dev_ctx->priv->dev, + "%s: Failed copy data to shared memory.", + dev_ctx->devname); + err = -EFAULT; + goto rollback; + } + } + + b_desc = add_b_desc_to_pending_list(dma_buf_ptr, &io, dev_ctx); + if (IS_ERR(b_desc)) { + err = PTR_ERR(b_desc); + dev_err(dev_ctx->priv->dev, "%s: Failed to allocate/link b_desc.\n", + dev_ctx->devname); + goto rollback; + } + +copy: + /* Provide the EdgeLock Enclave address to user space only if success.*/ + if (copy_to_user(uarg, &io, sizeof(io))) { + dev_err(dev_ctx->priv->dev, "%s: Failed to copy iobuff setup to user.\n", + dev_ctx->devname); + err = -EFAULT; + goto rollback; + } + return err; + +rollback: + if (!IS_ERR_OR_NULL(b_desc)) { + list_del(&b_desc->link); + kfree(b_desc); + } + + if (dma_buf_ptr && aligned_len) { + memset(dma_buf_ptr, 0, aligned_len); + rollback_shared_mem_pos(dev_ctx, aligned_len); + } + + return err; +} + +/* IOCTL to provide SoC information */ +static int se_ioctl_get_se_soc_info_handler(struct se_if_device_ctx *dev_ctx, + void __user *uarg) +{ + struct se_ioctl_get_soc_info soc_info; + int err = -EINVAL; + + soc_info.soc_id = get_se_soc_id(dev_ctx->priv); + soc_info.soc_rev = var_se_info.soc_rev; + + err = copy_to_user(uarg, (u8 *)(&soc_info), sizeof(soc_info)); + if (err) { + dev_err(dev_ctx->priv->dev, "%s: Failed to copy soc info to user.\n", + dev_ctx->devname); + err = -EFAULT; + } + + return err; +} + +/* + * File operations for user-space + */ + +/* Write a message to the MU. */ +static ssize_t se_if_fops_write(struct file *fp, const char __user *buf, + size_t size, loff_t *ppos) +{ + struct se_if_device_ctx *dev_ctx = fp->private_data; + struct se_if_priv *priv; + int err; + + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &dev_ctx->fops_lock) { + if (dev_ctx->cleanup_done) + return -ENODEV; + + priv = dev_ctx->priv; + + dev_dbg(priv->dev, "%s: write from buf (%p)%zu, ppos=%lld.\n", dev_ctx->devname, + buf, size, ((ppos) ? *ppos : 0)); + + if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) { + se_dev_ctx_shared_mem_cleanup(dev_ctx); + return -EINVAL; + } + + if (size < SE_MU_HDR_SZ || size > MAX_ALLOWED_TX_MSG_SZ) { + dev_err(priv->dev, "%s: User buffer too small/large(%zu < %d)\n", + dev_ctx->devname, size, + size < SE_MU_HDR_SZ ? SE_MU_HDR_SZ : + MAX_ALLOWED_TX_MSG_SZ); + return -ENOSPC; + } + + struct se_api_msg *tx_msg __free(kfree) = memdup_user(buf, size); + if (IS_ERR(tx_msg)) + return PTR_ERR(tx_msg); + + err = se_chk_tx_rsp_msg_hdr(dev_ctx, &tx_msg->header, size); + if (err) + return err; + + print_hex_dump_debug("from user ", DUMP_PREFIX_OFFSET, 4, 4, + tx_msg, size, false); + + err = ele_msg_send(dev_ctx, tx_msg, size); + + return err; + } +} + +/* + * Read a message from the MU. + * Blocking until a message is available. + */ +static ssize_t se_if_fops_read(struct file *fp, char __user *buf, size_t size, + loff_t *ppos) +{ + struct se_if_device_ctx *dev_ctx = fp->private_data; + u8 rx_msg_snap[MAX_NVM_MSG_LEN] = {}; + char devname_snap[32] = {}; + struct se_if_priv *priv; + unsigned long flags; + size_t copy_len; + int err; + + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &dev_ctx->fops_lock) { + priv = dev_ctx->priv; + + if (dev_ctx->cleanup_done) + return -ENODEV; + + /* + * Snapshot devname once while fops_lock is held. After the + * scoped guard releases the lock, a concurrent cleanup_dev_ctx() + * could free dev_ctx->devname before the error path below runs. + */ + strscpy(devname_snap, dev_ctx->devname, sizeof(devname_snap)); + + dev_dbg(priv->dev, "%s: read to buf %p(%zu), ppos=%lld.\n", devname_snap, + buf, size, ((ppos) ? *ppos : 0)); + + mutex_lock(&priv->modify_lock); + if (dev_ctx != priv->cmd_receiver_clbk_hdl.dev_ctx) { + mutex_unlock(&priv->modify_lock); + se_dev_ctx_shared_mem_cleanup(dev_ctx); + return -EINVAL; + } + mutex_unlock(&priv->modify_lock); + } + + err = ele_msg_rcv(dev_ctx, &priv->cmd_receiver_clbk_hdl); + if (err < 0) { + if (err != -ERESTARTSYS) + dev_err(priv->dev, + "%s: Er[0x%x]: Signal Interrupted. Current act-dev-ctx count: %d.", + devname_snap, err, dev_ctx->priv->active_devctx_count); + return err; + } + + /* + * Reacquire fops_lock before touching any dev_ctx state (pending lists, + * rx_msg) after the blocking wait. fops_lock was dropped before calling + * ele_msg_rcv(). If cleanup_dev_ctx() ran concurrently it could have + * freed the DMA buffers and the pending lists, leading to UAF and list + * corruption. Re-checking cleanup_done under fops_lock prevents that. + */ + mutex_lock(&dev_ctx->fops_lock); + + if (dev_ctx->cleanup_done) { + mutex_unlock(&dev_ctx->fops_lock); + return -ENODEV; + } + + /* + * Snapshot the whole rx_msg under modify_lock + clbk_rx_lock, not just + * copy_len bytes: fw_api_specific_ops() reads data words (e.g. strg_hdl + * at data[1]) beyond the userspace read size; truncating would record a + * zero handle. Run fw_api_specific_ops() OUTSIDE modify_lock + * (ELE_STORAGE_OPEN_REQ re-takes it, else deadlock). + */ + scoped_guard(mutex, &priv->modify_lock) { + spin_lock_irqsave(&priv->cmd_receiver_clbk_hdl.clbk_rx_lock, flags); + if (priv->cmd_receiver_clbk_hdl.dev_ctx != dev_ctx || + !priv->cmd_receiver_clbk_hdl.rx_msg || + !priv->cmd_receiver_clbk_hdl.rx_msg_sz) { + spin_unlock_irqrestore(&priv->cmd_receiver_clbk_hdl.clbk_rx_lock, flags); + mutex_unlock(&dev_ctx->fops_lock); + return -ENODEV; + } + copy_len = min(size, (size_t)priv->cmd_receiver_clbk_hdl.rx_msg_sz); + memcpy(rx_msg_snap, priv->cmd_receiver_clbk_hdl.rx_msg, + priv->cmd_receiver_clbk_hdl.rx_msg_sz); + priv->cmd_receiver_clbk_hdl.rx_msg_sz = 0; + spin_unlock_irqrestore(&priv->cmd_receiver_clbk_hdl.clbk_rx_lock, flags); + + /* We may need to copy the output data to user before + * delivering the completion message. + */ + err = se_dev_ctx_cpy_out_data(dev_ctx); + if (err < 0) { + se_dev_ctx_shared_mem_cleanup(dev_ctx); + mutex_unlock(&dev_ctx->fops_lock); + return err; + } + } + + /* fw_api_specific_ops() runs outside modify_lock; see comment above. */ + print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4, + rx_msg_snap, copy_len, false); + + cmd_receiver_specific_ops(dev_ctx, (struct se_api_msg *)rx_msg_snap); + err = copy_len; + if (copy_to_user(buf, rx_msg_snap, copy_len)) + err = -EFAULT; + + se_dev_ctx_shared_mem_cleanup(dev_ctx); + mutex_unlock(&dev_ctx->fops_lock); + + return err; +} + +/* Open a character device. */ +static int se_if_fops_open(struct inode *nd, struct file *fp) +{ + struct miscdevice *miscdev = fp->private_data; + struct se_if_open_gate *gate; + struct se_if_device_ctx *misc_dev_ctx; + struct se_if_device_ctx *dev_ctx; + struct se_if_priv *priv; + int err = 0; + + gate = container_of(miscdev, struct se_if_open_gate, miscdev); + + if (!se_if_open_gate_get(gate)) + return -ENODEV; + + if (mutex_lock_interruptible(&gate->lock)) { + se_if_open_gate_put(gate); + return -ERESTARTSYS; + } + + if (gate->dying || !gate->priv || + !kref_get_unless_zero(&gate->priv->refcount)) { + mutex_unlock(&gate->lock); + se_if_open_gate_put(gate); + return -ENODEV; + } + + priv = gate->priv; + mutex_unlock(&gate->lock); + + misc_dev_ctx = priv->priv_dev_ctx; + + if (mutex_lock_interruptible(&misc_dev_ctx->fops_lock)) { + err = -ERESTARTSYS; + goto out_put_priv; + } + + if (misc_dev_ctx->cleanup_done) { + err = -ENODEV; + goto out_unlock_misc; + } + + priv->dev_ctx_mono_count++; + err = init_device_context(priv, priv->dev_ctx_mono_count, &dev_ctx); + if (err) { + dev_err(priv->dev, "Failed to create dev-ctx.\n"); + goto out_unlock_misc; + } + + fp->private_data = dev_ctx; + +out_unlock_misc: + mutex_unlock(&misc_dev_ctx->fops_lock); +out_put_priv: + kref_put(&priv->refcount, se_if_priv_release); + se_if_open_gate_put(gate); + return err; +} + +/* Close a character device. */ +static int se_if_fops_close(struct inode *nd, struct file *fp) +{ + struct se_if_device_ctx *dev_ctx = fp->private_data; + + dlink_n_cleanup_dev_ctx(dev_ctx, true); + + return 0; +} + +/* IOCTL entry point of a character device */ +static long se_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + struct se_if_device_ctx *dev_ctx = fp->private_data; + struct se_if_priv *priv; + void __user *uarg = (void __user *)arg; + long err; + + /* Prevent race during change of device context */ + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &dev_ctx->fops_lock) { + if (dev_ctx->cleanup_done) + return -ENODEV; + + priv = dev_ctx->priv; + + switch (cmd) { + case SE_IOCTL_CHECK_CMD_RCV_REG_STATUS: { + guard(mutex)(&priv->modify_lock); + err = check_cmd_rcvr_status(dev_ctx); + break; + } + case SE_IOCTL_GET_MU_INFO: + err = se_ioctl_get_mu_info(dev_ctx, uarg); + break; + case SE_IOCTL_SETUP_IOBUF: + err = se_ioctl_setup_iobuf_handler(dev_ctx, uarg); + break; + case SE_IOCTL_GET_SOC_INFO: + err = se_ioctl_get_se_soc_info_handler(dev_ctx, uarg); + break; + case SE_IOCTL_CMD_SEND_RCV_RSP: + err = se_ioctl_cmd_snd_rcv_rsp_handler(dev_ctx, uarg); + break; + default: + err = -ENOTTY; + dev_dbg(priv->dev, "%s: IOCTL %.8x not supported.\n", + dev_ctx->devname, cmd); + } + } + + return err; +} + +/* Char driver setup */ +static const struct file_operations se_if_fops = { + .open = se_if_fops_open, + .owner = THIS_MODULE, + .release = se_if_fops_close, + .unlocked_ioctl = se_ioctl, + .compat_ioctl = compat_ptr_ioctl, + .read = se_if_fops_read, + .write = se_if_fops_write, +}; + +int se_get_mem_pool_buf(struct se_if_device_ctx *dev_ctx, void **buf, + dma_addr_t *daddr, u32 len) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct se_if_priv *priv = dev_ctx->priv; + struct se_buf_desc *b_desc = NULL; + + lockdep_assert_held(&dev_ctx->fops_lock); + + if (se_is_fw_busy_ctx(dev_ctx)) + return -EBUSY; + + b_desc = kzalloc_obj(*b_desc); + if (!b_desc) + return -ENOMEM; + + /* + * gen_pool is internally thread-safe, so contexts may allocate + * concurrently. The buffer is tracked on this context's own + * mem_pool_buf_list and released on its cleanup path. + */ + *buf = gen_pool_dma_alloc(priv->mem_pool, len, daddr); + if (!*buf) { + dev_err(priv->dev, "Failed to alloc from gen_pool.\n"); + kfree(b_desc); + return -ENOMEM; + } + + /* gen_pool_dma_alloc() does not zero the buffer. */ + memset(*buf, 0, len); + b_desc->shared_buf_ptr = *buf; + b_desc->size = len; + + list_add_tail(&b_desc->link, &se_shared_mem_mgmt->mem_pool_buf_list); + + return 0; +} + +void se_cleanup_mem_pool_buf(struct se_if_device_ctx *dev_ctx, bool reclaim) +{ + struct se_shared_mem_mgmt_info *se_shared_mem_mgmt = &dev_ctx->se_shared_mem_mgmt; + struct se_if_priv *priv = dev_ctx->priv; + struct se_buf_desc *b_desc, *temp; + + /* + * Free only the buffers this context allocated. A context that never + * used the pool has an empty list, so this is a no-op for it. + * + * Unlike the coherent staging buffer, the pool path needs no + * "nothing staged" (pos) gate on the reclaim=false leg. Pool buffers + * are ephemeral, per-transaction allocations: se_get_mem_pool_buf() + * refuses to allocate once the context is fw_busy, ele_msg_send_rcv() + * refuses to start a new command while fw_busy, and the success path + * frees the whole list via se_cleanup_mem_pool_buf(reclaim=true) + * before returning. se_if_cmd_lock serialises synchronous commands, so + * at most one transaction is outstanding. The only way to reach here + * with reclaim=false and a non-empty list is the single fw_busy + * context still owning the buffer(s) from the one timed-out + * transaction. Those buffers are exactly the in-flight ones the + * enclave may still be DMA-ing into, so leaving them on the list (no + * gen_pool_free) deliberately leaks them to avoid a DMA-after-free - + * there are no already-consumed pool buffers to reclaim on this leg. + */ + list_for_each_entry_safe(b_desc, temp, &se_shared_mem_mgmt->mem_pool_buf_list, link) { + if (reclaim) + gen_pool_free(priv->mem_pool, + (unsigned long)b_desc->shared_buf_ptr, + b_desc->size); + list_del(&b_desc->link); + kfree(b_desc); + } +} + +static void se_fw_busy_work(struct work_struct *work) +{ + struct fw_busy_info *fbusy_info = + container_of(work, struct fw_busy_info, fw_busy_work); + struct se_if_priv *priv = + container_of(fbusy_info, struct se_if_priv, fw_busy_info); + + se_clear_fw_busy(priv); +} + static int se_suspend(struct device *dev) { struct se_if_priv *priv = dev_get_drvdata(dev); diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h index dd4a1ea7e35a..c05328f3b408 100644 --- a/drivers/firmware/imx/se_ctrl.h +++ b/drivers/firmware/imx/se_ctrl.h @@ -10,20 +10,43 @@ #include #include #include +#include +#define MAX_DEVNAME_SZ 64 #define MAX_FW_LOAD_RETRIES 50 #define SE_MSG_WORD_SZ 0x4 #define RES_STATUS(x) FIELD_GET(0x000000ff, x) +#define MAX_DATA_SIZE_PER_USER (128 * 1024) #define MAX_NVM_MSG_LEN (256) +/* Largest firmware response buffer size in bytes; equals ELE_DEBUG_DUMP_RSP_SZ (0x5c). */ +#define MAX_ALLOWED_RX_MSG_SZ 0x5c #define MESSAGING_VERSION_6 0x6 #define MESSAGING_VERSION_7 0x7 +struct se_if_open_gate { + struct miscdevice miscdev; + struct se_if_priv *priv; + /* to lock to update the structure */ + struct mutex lock; + struct kref refcount; + bool dying; + /* set once misc_register() has succeeded (deferred to probe end) */ + bool registered; +}; + struct se_clbk_handle { struct se_if_device_ctx *dev_ctx; struct completion done; bool signal_rcvd; + /* + * Set under clbk_rx_lock once a real response is copied into rx_msg, + * cleared when a new transaction is armed. Lets ele_msg_rcv() tell a + * genuine response from a teardown-forced complete_all() with no data. + */ + bool rx_delivered; u32 rx_msg_sz; + /* * Assignment of the rx_msg buffer to held till the * received content as part callback function, is copied. @@ -45,10 +68,46 @@ struct se_imem_buf { u32 state; }; +struct se_buf_desc { + u8 *shared_buf_ptr; + void __user *usr_buf_ptr; + u32 size; + struct list_head link; +}; + +struct se_shared_mem { + dma_addr_t dma_addr; + u32 size; + u32 pos; + u8 *ptr; +}; + +struct se_shared_mem_mgmt_info { + struct list_head mem_pool_buf_list; + struct list_head pending_in; + struct list_head pending_out; + + struct se_shared_mem non_secure_mem; +}; + /* Private struct for each char device instance. */ struct se_if_device_ctx { struct se_if_priv *priv; + struct miscdevice *miscdev; const char *devname; + u32 sess_hdl; + u32 strg_hdl; + bool cleanup_done; + unsigned long rcv_msg_timeout_jiffies; + + /* process one file operation at a time. */ + struct mutex fops_lock; + + struct se_shared_mem_mgmt_info se_shared_mem_mgmt; + struct list_head link; + + /* Add reference counting */ + struct kref refcount; }; /* Header of the messages exchange with the EdgeLock Enclave */ @@ -90,6 +149,103 @@ struct se_fw_load_info { struct mutex load_fw_lock; }; +struct cmd_rcvr_data_info { + /* + * Tracks the last FW export command received by the command receiver + * (ELE_STORAGE_MASTER_EXPORT_REQ or ELE_STORAGE_CHUNK_EXPORT_REQ). + * Set by cmd_receiver_specific_ops() when the FW command arrives via + * read(), cleared at entry. se_cmd_receiver_allowed_rsp() checks it to + * ensure write() can only follow a matching read() for export responses. + * Stored per SE interface (not file-scope static) to prevent a race when + * multiple SE interfaces (e.g. ELE and V2X) run concurrent export flows. + */ + u8 cmd_rcvr_last_rcvd_cmd_id; + + /* + * Export buffer size communicated by the FW in the preceding + * ELE_STORAGE_MASTER_EXPORT_REQ or ELE_STORAGE_CHUNK_EXPORT_REQ + * command. cmd_receiver_specific_ops() stores it here; se_val_cmd_addrs() + * reads it when size_idx == SE_CMD_RCVR_ADDR_VAR_SIZE to range-check + * the response buffer. Stored per SE interface so concurrent ELE and V2X + * export flows cannot corrupt each other's size. + */ + u32 cmd_rcvr_var_size; +}; + +struct fw_busy_info { + /* + * fw_busy acts as a circuit breaker: set when a synchronous + * transaction times out, cleared when the late FW response + * arrives and se_clear_fw_busy() has reclaimed the parked + * dev_ctx. + */ + atomic_t fw_busy; + + /* + * Serialise fw_busy, fw_busy_dev_ctx state updates between the + * timeout path, late-response callback/work, and teardown. + */ + spinlock_t fw_busy_lock; + + /* + * dev_ctx whose synchronous transaction timed out; parked here + * so a late FW response can still be routed to it by + * se_clear_fw_busy(). + */ + struct se_if_device_ctx *fw_busy_dev_ctx; + + /* + * Snapshot of fw_busy_dev_ctx->devname, captured under + * fw_busy_lock at arm time in se_mark_fw_busy(). cleanup_dev_ctx() + * frees dev_ctx->devname (and sets it to NULL) when a userspace fd + * is closed while the breaker is armed, so the parked dev_ctx may + * carry a NULL devname by the time se_clear_fw_busy() runs on a late + * FW response. Use this stable copy for diagnostics instead. Sized to + * match the "%s0_ch%d" devname and the char devname_snap[32] buffers + * used elsewhere in this driver. + */ + char devname[MAX_DEVNAME_SZ]; + + /* work item scheduled by se_if_rx_callback() on late response. */ + struct work_struct fw_busy_work; + + /* + * Snapshot of the orphaned firmware response that triggered + * fw_busy_work. Written once (under clbk_rx_lock, before + * schedule_work()) and read once (in se_clear_fw_busy(), under + * clbk_rx_lock). Sized to MAX_ALLOWED_RX_MSG_SZ (= ELE_DEBUG_DUMP_RSP_SZ, + * the largest firmware response) to accommodate any FW reply. + */ + u8 orphan_fw_rx_msg[MAX_ALLOWED_RX_MSG_SZ]; +}; + +struct msg_excl_flow_info { + /* + * Optional exclusive reservation of the SE messaging interface for a + * single flow. A flow that needs ele_msg_send_rcv() reserved to itself + * (e.g. the fw_busy recovery in se_clear_fw_busy()) publishes its own + * task here via se_reserve_msg_if() from OUTSIDE ele_msg_send_rcv(), and + * releases it with se_release_msg_if() when done. While non-NULL, + * ele_msg_send_rcv() lets only this owning task through and rejects every + * other caller with -EBUSY; while NULL the interface is open to general + * se_if_cmd_lock-based message exchange. Written under msg_excl_lock, + * read locklessly in ele_msg_send_rcv() via READ_ONCE and only ever + * compared against current, so a stale read is harmless (a non-owner can + * never match). + */ + struct task_struct *msg_excl_owner; + /* Serialise updates to msg_excl_owner. */ + spinlock_t msg_excl_lock; + /* + * Serialises competing reservation flows. se_reserve_msg_if() holds + * this mutex for the whole duration of a reservation, so a second flow + * that wants exclusive ownership of the messaging interface sleeps here + * until the current owner calls se_release_msg_if(). Held only from + * process/workqueue context. + */ + struct mutex msg_excl_flow_lock; +}; + struct se_if_priv { struct device *dev; @@ -99,12 +255,14 @@ struct se_if_priv { * under se_if_cmd_lock. */ struct se_clbk_handle waiting_rsp_clbk_hdl; + /* * prevent new command to be sent on the se interface while previous * command is still processing. (response is awaited) */ struct mutex se_if_cmd_lock; + struct msg_excl_flow_info msg_excl_flow; struct mbox_client se_mb_cl; struct mbox_chan *tx_chan, *rx_chan; @@ -112,10 +270,40 @@ struct se_if_priv { const struct se_if_defines *if_defs; struct se_fw_load_info load_fw; - atomic_t fw_busy; + /* + * Set once teardown begins. New synchronous transactions are rejected + * and a teardown-forced completion is not mistaken for a real firmware + * response. + */ + atomic_t going_away; + struct fw_busy_info fw_busy_info; struct se_if_device_ctx *priv_dev_ctx; + struct list_head dev_ctx_list; + + /* prevent modifying priv member variable in parallel. */ + struct mutex modify_lock; + u32 active_devctx_count; + u32 dev_ctx_mono_count; + + /* Add reference counting */ + struct kref refcount; + + /* stable gate used by .open() */ + struct se_if_open_gate *open_gate; + struct cmd_rcvr_data_info crcvr_info; }; char *get_se_if_name(u8 se_if_id); +void unset_dev_ctx_as_command_receiver(struct se_if_device_ctx *dev_ctx); +int set_dev_ctx_as_command_receiver(struct se_if_device_ctx *dev_ctx); +bool se_is_fw_busy_ctx(struct se_if_device_ctx *dev_ctx); +void se_dev_ctx_shared_mem_cleanup(struct se_if_device_ctx *dev_ctx); +int get_shared_mem_slot(struct se_if_device_ctx *dev_ctx, + u32 *length, dma_addr_t *ele_dma_addr, void **ptr); +int se_get_mem_pool_buf(struct se_if_device_ctx *dev_ctx, void **buf, + dma_addr_t *daddr, u32 len); +void se_cleanup_mem_pool_buf(struct se_if_device_ctx *dev_ctx, bool reclaim); +int se_reserve_msg_if(struct se_if_priv *priv); +void se_release_msg_if(struct se_if_priv *priv); #endif diff --git a/include/uapi/linux/se_ioctl.h b/include/uapi/linux/se_ioctl.h new file mode 100644 index 000000000000..c7ce736b5ea4 --- /dev/null +++ b/include/uapi/linux/se_ioctl.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause*/ +/* + * Copyright 2025 NXP + */ + +#ifndef SE_IOCTL_H +#define SE_IOCTL_H + +#include + +#define SE_TYPE_STR_DBG "dbg" +#define SE_TYPE_STR_HSM "hsm" +#define SE_TYPE_ID_UNKWN 0x0 +#define SE_TYPE_ID_DBG 0x1 +#define SE_TYPE_ID_HSM 0x2 +/* IOCTL definitions. */ + +struct se_ioctl_setup_iobuf { + __u64 user_buf; + __u32 length; + __u32 flags; + __u64 ele_addr; +}; + +struct se_ioctl_shared_mem_cfg { + __u32 base_offset; + __u32 size; +}; + +struct se_ioctl_get_if_info { + __u8 se_if_id; + __u8 interrupt_idx; + __u8 tz; + __u8 did; + __u8 cmd_tag; + __u8 rsp_tag; + __u8 success_tag; + __u8 base_api_ver; + __u8 fw_api_ver; +}; + +struct se_ioctl_cmd_snd_rcv_rsp_info { + __u64 tx_buf; + __u64 rx_buf; + __u32 tx_buf_sz; + __u32 rx_buf_sz; +}; + +struct se_ioctl_get_soc_info { + __u16 soc_id; + __u16 soc_rev; +}; + +/* IO Buffer Flags */ +#define SE_IO_BUF_FLAGS_IS_OUTPUT (0x00u) +#define SE_IO_BUF_FLAGS_IS_INPUT (0x01u) +#define SE_IO_BUF_FLAGS_USE_SEC_MEM (0x02u) +#define SE_IO_BUF_FLAGS_USE_SHORT_ADDR (0x04u) +#define SE_IO_BUF_FLAGS_IS_IN_OUT (0x10u) + +/* IOCTLS */ +#define SE_IOCTL 0x0A /* like MISC_MAJOR. */ + +/* + * ioctl to designated the current fd as logical-receiver. + * This ioctl is send when the nvm-daemon, a slave to the + * firmware is started by the user. + */ +#define SE_IOCTL_CHECK_CMD_RCV_REG_STATUS _IO(SE_IOCTL, 0x01) + +/* + * ioctl to get the buffer allocated from the memory, which is shared + * between kernel and FW. + * Post allocation, the kernel tagged the allocated memory with: + * Output + * Input + * Input-Output + * Short address + * Secure-memory + */ +#define SE_IOCTL_SETUP_IOBUF _IOWR(SE_IOCTL, 0x03, struct se_ioctl_setup_iobuf) + +/* + * ioctl to get the mu information, that is used to exchange message + * with FW, from user-space. + */ +#define SE_IOCTL_GET_MU_INFO _IOR(SE_IOCTL, 0x04, struct se_ioctl_get_if_info) +/* + * ioctl to get SoC Info from user-space. + */ +#define SE_IOCTL_GET_SOC_INFO _IOR(SE_IOCTL, 0x06, struct se_ioctl_get_soc_info) + +/* + * ioctl to send command and receive response from user-space. + */ +#define SE_IOCTL_CMD_SEND_RCV_RSP _IOWR(SE_IOCTL, 0x07, struct se_ioctl_cmd_snd_rcv_rsp_info) +#endif -- cgit v1.2.3 From 52116bd83ae2c316214955e2fd4d5044594be934 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:10:03 +0530 Subject: arm64: dts: imx8ulp: add secure enclave node Add the EdgeLock Enclave (ELE) secure-enclave node to the i.MX8ULP SoC dtsi, together with a label for sram@2201f000 that the node references. Keep the node disabled in the SoC dtsi so it does not impose a reserved-memory requirement on every board. Boards enable the enclave and provide its memory-region by including imx8ulp-firmware.dtsi. Signed-off-by: Pankaj Gupta Reviewed-by: Frank Li Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi index 777b89ed6849..ac8293f81c6b 100644 --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright 2021 NXP + * Copyright 2021, 2025 NXP */ #include @@ -154,7 +154,7 @@ #clock-cells = <0>; }; - sram@22010000 { + sram0: sram@22010000 { compatible = "mmio-sram"; reg = <0x0 0x22010000 0x0 0x10000>; @@ -186,6 +186,14 @@ #thermal-sensor-cells = <1>; }; }; + + hsm0: secure-enclave { + compatible = "fsl,imx8ulp-se-ele-hsm"; + mbox-names = "tx", "rx"; + mboxes = <&s4muap 0 0>, <&s4muap 1 0>; + sram = <&sram0>; + status = "disabled"; + }; }; cm33: remoteproc-cm33 { -- cgit v1.2.3 From 88b9dc37d9d84b516ecec8aca00ef15a1ddb119d Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 15 Sep 2026 01:10:04 +0530 Subject: arm64: dts: imx8ulp: add reserved memory for EdgeLock Enclave Reserve 1MB of DDR for the EdgeLock Enclave. The enclave hardware can only access DDR in the 0x80000000 - 0xafffffff window, so constrain the pool to that range with alloc-ranges and let the kernel choose the placement rather than hardcoding an address. Provide this as a shared imx8ulp-firmware.dtsi that also enables the hsm0 node and wires up its memory-region, so every i.MX8ULP board can bring up the enclave with a single include instead of duplicating the reserved memory node. Include it from imx8ulp-evk. Signed-off-by: Pankaj Gupta Reviewed-by: Frank Li Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8ulp-evk.dts | 3 ++- .../arm64/boot/dts/freescale/imx8ulp-firmware.dtsi | 31 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/boot/dts/freescale/imx8ulp-firmware.dtsi diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts index 4b925832bb66..5fe58a025cfd 100644 --- a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts @@ -1,12 +1,13 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright 2021 NXP + * Copyright 2021, 2025 NXP */ /dts-v1/; #include #include "imx8ulp.dtsi" +#include "imx8ulp-firmware.dtsi" / { model = "NXP i.MX8ULP EVK"; diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-firmware.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp-firmware.dtsi new file mode 100644 index 000000000000..e4bc352f68af --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8ulp-firmware.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2025 NXP + * + * Default reserved memory and EdgeLock Enclave (ELE) enablement shared by + * i.MX8ULP boards. Include this from a board dts to bring up the secure + * enclave without having to duplicate the reserved-memory node. The ELE + * hardware can only access DDR in the 0x80000000 - 0xafffffff window, so the + * pool is constrained to that range with alloc-ranges and the kernel is left + * to place the 1 MiB region. + */ + +/ { + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ele_reserved: ele-reserved { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x80000000 0 0x30000000>; + size = <0 0x100000>; + no-map; + }; + }; +}; + +&hsm0 { + memory-region = <&ele_reserved>; + status = "okay"; +}; -- cgit v1.2.3 From c4e5f1a143799651aba2c4f66860b63b56786306 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:07:57 +0800 Subject: arm64: dts: imx8dxl-evk: fix reserved memory node names for remoteproc The imx_rproc driver uses node names to identify reserved memory regions. It checks for "vdev0buffer" to skip mapping, "rsc-table" to locate the resource table, and "vdev" prefix to filter vdev regions. Rename the reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: ee39dbd9a6cb ("arm64: dts: imx8dxl-evk: add imx8dxl_cm4, lsio mu5, related memory region") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8dxl-evk.dts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts index 0ede0c7ed422..71eff3efa6d3 100644 --- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts @@ -29,7 +29,7 @@ clocks = <&clk_dummy>; mbox-names = "tx", "rx", "rxdb"; mboxes = <&lsio_mu5 0 1 &lsio_mu5 1 1 &lsio_mu5 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>; fsl,resource-id = ; @@ -65,32 +65,32 @@ linux,cma-default; }; - vdev0vring0: memory0@90000000 { + vdev0vring0: vdev0vring0@90000000 { reg = <0 0x90000000 0 0x8000>; no-map; }; - vdev0vring1: memory@90008000 { + vdev0vring1: vdev0vring1@90008000 { reg = <0 0x90008000 0 0x8000>; no-map; }; - vdev1vring0: memory@90010000 { + vdev1vring0: vdev1vring0@90010000 { reg = <0 0x90010000 0 0x8000>; no-map; }; - vdev1vring1: memory@90018000 { + vdev1vring1: vdev1vring1@90018000 { reg = <0 0x90018000 0 0x8000>; no-map; }; - rsc_table: memory-rsc-table@900ff000 { + rsc_table: rsc-table@900ff000 { reg = <0 0x900ff000 0 0x1000>; no-map; }; - vdevbuffer: memory-vdevbuffer@90400000 { + vdev0buffer: vdev0buffer@90400000 { compatible = "shared-dma-pool"; reg = <0 0x90400000 0 0x100000>; no-map; -- cgit v1.2.3 From c712a46c10d38ce7869a9d81d7986e844a4e9f24 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:07:58 +0800 Subject: arm64: dts: imx8qm-mek: fix reserved memory node names for remoteproc The imx_rproc driver uses node names to identify reserved memory regions. It checks for "vdev0buffer" to skip mapping, "rsc-table" to locate the resource table, and "vdev" prefix to filter vdev regions. Rename the reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: 52c9971edd4f ("arm64: dts: imx8qm-mek: add cm4 remote-proc and related memory region") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qm-mek.dts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts index 9e49ac377162..8b67fb5d670d 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts +++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts @@ -44,57 +44,57 @@ #size-cells = <2>; ranges; - vdev0vring0: memory@90000000 { + vdev0vring0: vdev0vring0@90000000 { reg = <0 0x90000000 0 0x8000>; no-map; }; - vdev0vring1: memory@90008000 { + vdev0vring1: vdev0vring1@90008000 { reg = <0 0x90008000 0 0x8000>; no-map; }; - vdev1vring0: memory@90010000 { + vdev1vring0: vdev1vring0@90010000 { reg = <0 0x90010000 0 0x8000>; no-map; }; - vdev1vring1: memory@90018000 { + vdev1vring1: vdev1vring1@90018000 { reg = <0 0x90018000 0 0x8000>; no-map; }; - rsc_table0: memory@900ff000 { + rsc_table0: rsc-table@900ff000 { reg = <0 0x900ff000 0 0x1000>; no-map; }; - vdev2vring0: memory@90100000 { + vdev2vring0: vdev2vring0@90100000 { reg = <0 0x90100000 0 0x8000>; no-map; }; - vdev2vring1: memory@90108000 { + vdev2vring1: vdev2vring1@90108000 { reg = <0 0x90108000 0 0x8000>; no-map; }; - vdev3vring0: memory@90110000 { + vdev3vring0: vdev3vring0@90110000 { reg = <0 0x90110000 0 0x8000>; no-map; }; - vdev3vring1: memory@90118000 { + vdev3vring1: vdev3vring1@90118000 { reg = <0 0x90118000 0 0x8000>; no-map; }; - rsc_table1: memory@901ff000 { + rsc_table1: rsc-table@901ff000 { reg = <0 0x901ff000 0 0x1000>; no-map; }; - vdevbuffer: memory@90400000 { + vdev0buffer: vdev0buffer@90400000 { compatible = "shared-dma-pool"; reg = <0 0x90400000 0 0x100000>; no-map; @@ -456,7 +456,7 @@ mboxes = <&lsio_mu5 0 1 &lsio_mu5 1 1 &lsio_mu5 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table0>; power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>; @@ -471,7 +471,7 @@ mboxes = <&lsio_mu6 0 1 &lsio_mu6 1 1 &lsio_mu6 3 1>; - memory-region = <&vdevbuffer>, <&vdev2vring0>, <&vdev2vring1>, + memory-region = <&vdev0buffer>, <&vdev2vring0>, <&vdev2vring1>, <&vdev3vring0>, <&vdev3vring1>, <&rsc_table1>; power-domains = <&pd IMX_SC_R_M4_1_PID0>, <&pd IMX_SC_R_M4_1_MU_1A>; -- cgit v1.2.3 From 2cd565bde7e872409fa468fb9410e539fb5969e4 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:07:59 +0800 Subject: arm64: dts: imx8qm-mek: fix dsp reserved memory node names for remoteproc The imx_dsp_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "memory", the check fails and the region gets unnecessarily mapped. Rename the DSP reserved memory nodes to use proper names for consistency with other remoteproc reserved memory regions and to ensure the vdev0buffer check works correctly. Rename the DSP reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: d0ee7ae8ce26 ("arm64: dts: imx8qm-mek: enable dsp node for rproc usage") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qm-mek.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts index 8b67fb5d670d..1afa65bd955e 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts +++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts @@ -105,17 +105,17 @@ no-map; }; - dsp_vdev0vring0: memory@942f0000 { + dsp_vdev0vring0: vdev0vring0@942f0000 { reg = <0 0x942f0000 0 0x8000>; no-map; }; - dsp_vdev0vring1: memory@942f8000 { + dsp_vdev0vring1: vdev0vring1@942f8000 { reg = <0 0x942f8000 0 0x8000>; no-map; }; - dsp_vdev0buffer: memory@94300000 { + dsp_vdev0buffer: vdev0buffer@94300000 { compatible = "shared-dma-pool"; reg = <0 0x94300000 0 0x100000>; no-map; -- cgit v1.2.3 From a9f3cf4354022ca0b4a0d12eab7af9858f71c9f7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:00 +0800 Subject: arm64: dts: imx8qxp-mek: fix reserved memory node names for remoteproc The imx_rproc driver uses node names to identify reserved memory regions. It checks for "vdev0buffer" to skip mapping, "rsc-table" to locate the resource table, and "vdev" prefix to filter vdev regions. Rename the reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: 5fa302590f17 ("arm64: dts: imx8qxp-mek: add cm4 and related nodes") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qxp-mek.dts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts index 857a6e512228..6322ff471175 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts +++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts @@ -27,7 +27,7 @@ mboxes = <&lsio_mu5 0 1 &lsio_mu5 1 1 &lsio_mu5 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>; @@ -242,32 +242,32 @@ #size-cells = <2>; ranges; - vdev0vring0: memory@90000000 { + vdev0vring0: vdev0vring0@90000000 { reg = <0 0x90000000 0 0x8000>; no-map; }; - vdev0vring1: memory@90008000 { + vdev0vring1: vdev0vring1@90008000 { reg = <0 0x90008000 0 0x8000>; no-map; }; - vdev1vring0: memory@90010000 { + vdev1vring0: vdev1vring0@90010000 { reg = <0 0x90010000 0 0x8000>; no-map; }; - vdev1vring1: memory@90018000 { + vdev1vring1: vdev1vring1@90018000 { reg = <0 0x90018000 0 0x8000>; no-map; }; - rsc_table: memory@900ff000 { + rsc_table: rsc-table@900ff000 { reg = <0 0x900ff000 0 0x1000>; no-map; }; - vdevbuffer: memory@90400000 { + vdev0buffer: vdev0buffer@90400000 { compatible = "shared-dma-pool"; reg = <0 0x90400000 0 0x100000>; no-map; -- cgit v1.2.3 From 715f8f8877d03025a2af98b4128c83441617eb74 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:01 +0800 Subject: arm64: dts: imx8qxp-mek: fix dsp reserved memory node names for remoteproc The imx_dsp_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "memory", the check fails and the region gets unnecessarily mapped. Rename the DSP reserved memory nodes to use proper names for consistency with other remoteproc reserved memory regions and to ensure the vdev0buffer check works correctly. Rename the DSP reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: f3e22e1d8171 ("arm64: dts: imx8qxp-mek: add dsp rproc-related mem regions") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8qxp-mek.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts index 6322ff471175..eb994f3e2872 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts +++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts @@ -273,17 +273,17 @@ no-map; }; - dsp_vdev0vring0: memory@942f0000 { + dsp_vdev0vring0: vdev0vring0@942f0000 { reg = <0 0x942f0000 0 0x8000>; no-map; }; - dsp_vdev0vring1: memory@942f8000 { + dsp_vdev0vring1: vdev0vring1@942f8000 { reg = <0 0x942f8000 0 0x8000>; no-map; }; - dsp_vdev0buffer: memory@94300000 { + dsp_vdev0buffer: vdev0buffer@94300000 { compatible = "shared-dma-pool"; reg = <0 0x94300000 0 0x100000>; no-map; -- cgit v1.2.3 From f55e49b75c65c3e38e7bbe1d735f79128a50126e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:02 +0800 Subject: arm64: dts: imx8ulp-evk: fix reserved memory node names for remoteproc The imx_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "vdevbuffer", the check fails and the region gets unnecessarily mapped. Rename it to "vdev0buffer" to match what the driver expects. Fixes: 014fbffa25a7 ("arm64: dts: imx8ulp-evk: enable CM33 node") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8ulp-evk.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts index 4b925832bb66..4e19847f240a 100644 --- a/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8ulp-evk.dts @@ -80,7 +80,7 @@ no-map; }; - vdevbuffer: vdevbuffer@a8400000 { + vdev0buffer: vdev0buffer@a8400000 { compatible = "shared-dma-pool"; reg = <0 0xa8400000 0 0x100000>; no-map; @@ -139,7 +139,7 @@ mboxes = <&mu 0 1>, <&mu 1 1>, <&mu 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; status = "okay"; }; -- cgit v1.2.3 From ab6fc27a020a18a765e17bc445b64ee18b6244de Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:03 +0800 Subject: arm64: dts: imx93-11x11-frdm: fix reserved memory node names for remoteproc The imx_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "vdevbuffer", the check fails and the region gets unnecessarily mapped. Rename it to "vdev0buffer" to match what the driver expects. Fixes: eb2f28413e23 ("arm64: dts: freescale: add support for NXP i.MX93 FRDM") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi index 97d89288db3c..33ed26aafde8 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm-common.dtsi @@ -100,7 +100,7 @@ no-map; }; - vdevbuffer: vdevbuffer@a4020000 { + vdev0buffer: vdev0buffer@a4020000 { compatible = "shared-dma-pool"; reg = <0 0xa4020000 0 0x100000>; no-map; @@ -122,7 +122,7 @@ <&mu1 1 1>, <&mu1 3 1>; mbox-names = "tx", "rx", "rxdb"; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; status = "okay"; }; -- cgit v1.2.3 From e62f7ef5320d05361ee7f665568d05361b0c59d9 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:04 +0800 Subject: arm64: dts: imx93-14x14-evk: fix reserved memory node names for remoteproc The imx_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "vdevbuffer", the check fails and the region gets unnecessarily mapped. Rename it to "vdev0buffer" to match what the driver expects. Fixes: 0481dadbc5e5 ("arm64: dts: imx93: support i.MX93-14x14-EVK board") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts index a025a08130f8..1081881028b2 100644 --- a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts @@ -101,7 +101,7 @@ no-map; }; - vdevbuffer: vdevbuffer@a4020000 { + vdev0buffer: vdev0buffer@a4020000 { compatible = "shared-dma-pool"; reg = <0 0xa4020000 0 0x100000>; no-map; @@ -255,7 +255,7 @@ mboxes = <&mu1 0 1>, <&mu1 1 1>, <&mu1 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; status = "okay"; }; -- cgit v1.2.3 From 475a58b82921cc89805b31e0bc1df91681124a3d Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:05 +0800 Subject: arm64: dts: imx93-9x9-qsb: fix reserved memory node names for remoteproc The imx_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "vdevbuffer", the check fails and the region gets unnecessarily mapped. Rename it to "vdev0buffer" to match what the driver expects. Fixes: 0565d20cd8c2 ("arm64: dts: freescale: Support i.MX93 9x9 Quick Start Board") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts index 4e31a78963fe..3be5bf4bc101 100644 --- a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts +++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts @@ -77,7 +77,7 @@ no-map; }; - vdevbuffer: vdevbuffer@a4020000 { + vdev0buffer: vdev0buffer@a4020000 { compatible = "shared-dma-pool"; reg = <0 0xa4020000 0 0x100000>; no-map; @@ -213,7 +213,7 @@ mboxes = <&mu1 0 1>, <&mu1 1 1>, <&mu1 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; status = "okay"; }; -- cgit v1.2.3 From d8aa7355f91ed71502f588d33200a211f24f58ef Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:06 +0800 Subject: arm64: dts: imx8dxl-sr-som: fix reserved memory node names for remoteproc The imx_rproc driver uses node names to identify reserved memory regions. It checks for "vdev0buffer" to skip mapping, "rsc-table" to locate the resource table, and "vdev" prefix to filter vdev regions. Rename the reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: ef873f01a1b1 ("arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi index 93a0eb4d7f77..83d22ae373c3 100644 --- a/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8dxl-sr-som.dtsi @@ -26,7 +26,7 @@ clocks = <&clk_dummy>; mboxes = <&lsio_mu5 0 1 &lsio_mu5 1 1 &lsio_mu5 3 1>; mbox-names = "tx", "rx", "rxdb"; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; power-domains = <&pd IMX_SC_R_M4_0_PID0>, <&pd IMX_SC_R_M4_0_MU_1A>; fsl,entry-address = <0x34fe0000>; @@ -103,32 +103,32 @@ linux,cma-default; }; - vdev0vring0: memory0@90000000 { + vdev0vring0: vdev0vring0@90000000 { reg = <0 0x90000000 0 0x8000>; no-map; }; - vdev0vring1: memory@90008000 { + vdev0vring1: vdev0vring1@90008000 { reg = <0 0x90008000 0 0x8000>; no-map; }; - vdev1vring0: memory@90010000 { + vdev1vring0: vdev1vring0@90010000 { reg = <0 0x90010000 0 0x8000>; no-map; }; - vdev1vring1: memory@90018000 { + vdev1vring1: vdev1vring1@90018000 { reg = <0 0x90018000 0 0x8000>; no-map; }; - rsc_table: memory-rsc-table@900ff000 { + rsc_table: rsc-table@900ff000 { reg = <0 0x900ff000 0 0x1000>; no-map; }; - vdevbuffer: memory-vdevbuffer@90400000 { + vdev0buffer: vdev0buffer@90400000 { compatible = "shared-dma-pool"; reg = <0 0x90400000 0 0x100000>; no-map; -- cgit v1.2.3 From 7e92e62246c472418230b48c05e9296835b26b07 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:07 +0800 Subject: arm64: dts: imx93-11x11-evk: fix reserved memory node names for remoteproc The imx_rproc driver checks for the name "vdev0buffer" to skip mapping the vdev buffer region, as it is handled by rproc_add_virtio_dev. With the node named "vdevbuffer", the check fails and the region gets unnecessarily mapped. Rename it to "vdev0buffer" to match what the driver expects. Fixes: 3eb100e56195 ("arm64: dts: imx93: Extract common EVK description into shared dtsi") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi index 2f3f9ebd3345..164b5c17bfe1 100644 --- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi +++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi @@ -68,7 +68,7 @@ no-map; }; - vdevbuffer: vdevbuffer@a4020000 { + vdev0buffer: vdev0buffer@a4020000 { compatible = "shared-dma-pool"; reg = <0 0xa4020000 0 0x100000>; no-map; @@ -171,7 +171,7 @@ mboxes = <&mu1 0 1>, <&mu1 1 1>, <&mu1 3 1>; - memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; status = "okay"; }; -- cgit v1.2.3 From 5cae743b988da033a709bfa10739b1d34fe57e71 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 29 Jul 2026 21:08:08 +0800 Subject: arm64: dts: imx95-15x15-frdm: fix reserved memory node names for remoteproc The imx_rproc driver uses node names to identify reserved memory regions. It checks for "vdev0buffer" to skip mapping, "rsc-table" to locate the resource table, and "vdev" prefix to filter vdev regions. Rename the reserved memory nodes to use the expected names so the driver can correctly identify and handle each region. Fixes: 9bdfeed989b1 ("arm64: dts: freescale: imx95: Add support for i.MX95 15x15 FRDM board") Signed-off-by: Peng Fan Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts index ab1c1ccc9b6e..f82e149323d3 100644 --- a/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts +++ b/arch/arm64/boot/dts/freescale/imx95-15x15-frdm.dts @@ -189,33 +189,33 @@ linux,cma-default; }; - vdev0vring0: memory@88000000 { + vdev0vring0: vdev0vring0@88000000 { reg = <0 0x88000000 0 0x8000>; no-map; }; - vdev0vring1: memory@88008000 { + vdev0vring1: vdev0vring1@88008000 { reg = <0 0x88008000 0 0x8000>; no-map; }; - vdev1vring0: memory@88010000 { + vdev1vring0: vdev1vring0@88010000 { reg = <0 0x88010000 0 0x8000>; no-map; }; - vdev1vring1: memory@88018000 { + vdev1vring1: vdev1vring1@88018000 { reg = <0 0x88018000 0 0x8000>; no-map; }; - vdevbuffer: memory@88020000 { + vdev0buffer: vdev0buffer@88020000 { compatible = "shared-dma-pool"; reg = <0 0x88020000 0 0x100000>; no-map; }; - rsc_table: memory@88220000 { + rsc_table: rsc-table@88220000 { reg = <0 0x88220000 0 0x1000>; no-map; }; -- cgit v1.2.3 From e43e23cd502c1b154ed2e2c2d587b262663d2f7e Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:27 +0200 Subject: dt-bindings: arm: fsl: Add Lino iMX91/iMX93 Add bindings for the Toradex Lino iMX91 and Lino iMX93 SoMs, based on the NXP i.MX91 and i.MX93 SoCs, respectively. Lino SoMs use two board-to-board connectors to interface with a carrier board. They can also be mounted on the Lino-Verdin Adapter, which converts the Lino interface to the Toradex Verdin family pinout and allows the SoM to be used with Verdin-compatible carrier boards. The Lino-Verdin Adapter also provides a Wi-Fi/Bluetooth module, an Ethernet PHY and a GPIO expander. Add compatibles for systems consisting of a Lino SoM mounted on a Lino-Verdin Adapter and connected to either a Verdin Development Board or a Dahlia carrier board. Link: https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 Link: https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 Link: https://www.toradex.com/accessories/lino-verdin-adapter Link: https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit Link: https://www.toradex.com/products/carrier-board/verdin-development-board-kit Signed-off-by: Francesco Dolcini Acked-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index e16fe1ec7026..9a776d4e16be 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1511,6 +1511,15 @@ properties: - fsl,imx91-11x11-frdm-s # FRDM i.MX91S Development Board - const: fsl,imx91 + - description: i.MX91 boards with Toradex Lino Modules and Verdin Adapter + items: + - enum: + - toradex,lino-imx91-verdin-dahlia # Lino iMX91 Module on Verdin Dahlia Board + - toradex,lino-imx91-verdin-dev # Lino iMX91 Module on Verdin Dev Board + - const: toradex,lino-imx91-verdin # Lino iMX91 Module on Verdin Adapter + - const: toradex,lino-imx91 + - const: fsl,imx91 + - description: i.MX93 based Boards items: - enum: @@ -1522,6 +1531,15 @@ properties: - fsl,imx93-wireless-frdm # i.MX93 and IW610G WLCSP (Wi-Fi + BLE + 802.15.4) SiP FRDM Board - const: fsl,imx93 + - description: i.MX93 boards with Toradex Lino Modules and Verdin Adapter + items: + - enum: + - toradex,lino-imx93-verdin-dahlia # Lino iMX93 Module on Verdin Dahlia Board + - toradex,lino-imx93-verdin-dev # Lino iMX93 Module on Verdin Dev Board + - const: toradex,lino-imx93-verdin # Lino iMX93 Module on Verdin Adapter + - const: toradex,lino-imx93 + - const: fsl,imx93 + - description: i.MX94 based Boards items: - enum: -- cgit v1.2.3 From eea8de941daa56f75227b6778529f4ec78662bc0 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:28 +0200 Subject: dt-bindings: arm: fsl: Add Toradex OSM iMX91/iMX93 Add bindings for the Toradex OSM iMX91 and OSM iMX93 SoMs and the OSM Development Board they can be mated with. The Toradex OSM iMX91 and OSM iMX93 are OSM 1.2-compliant SoMs based on the NXP i.MX91 and i.MX93 SoCs, respectively. Link: https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx91 Link: https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx93 Link: https://www.toradex.com/products/carrier-board/osm-development-board Signed-off-by: Francesco Dolcini Acked-by: Krzysztof Kozlowski Signed-off-by: Frank Li --- Documentation/devicetree/bindings/arm/fsl.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 9a776d4e16be..9a80b1d08184 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -1520,6 +1520,12 @@ properties: - const: toradex,lino-imx91 - const: fsl,imx91 + - description: i.MX91 boards with Toradex OSM Modules + items: + - const: toradex,osm-imx91-dev # OSM iMX91 Module on OSM Dev Board + - const: toradex,osm-imx91 + - const: fsl,imx91 + - description: i.MX93 based Boards items: - enum: @@ -1540,6 +1546,12 @@ properties: - const: toradex,lino-imx93 - const: fsl,imx93 + - description: i.MX93 boards with Toradex OSM Modules + items: + - const: toradex,osm-imx93-dev # OSM iMX93 Module on OSM Dev Board + - const: toradex,osm-imx93 + - const: fsl,imx93 + - description: i.MX94 based Boards items: - enum: -- cgit v1.2.3 From 2f05e2f793b2282d591dc662d4e574929593669c Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:29 +0200 Subject: arm64: dts: freescale: Add Lino iMX93 Add support for the Lino iMX93 SoM, its Verdin adapter and development carrier board. The SoM is available in two variants, with i.MX91 or i.MX93 SoC, using the same PCB (the two chips are pin to pin compatible), to avoid duplication create a common dtsi to share commonalities. Link: https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 Link: https://www.toradex.com/accessories/lino-verdin-adapter Link: https://www.toradex.com/products/carrier-board/verdin-development-board-kit Co-developed-by: Emanuele Ghidoli Signed-off-by: Emanuele Ghidoli Co-developed-by: Ernest Van Hoecke Signed-off-by: Ernest Van Hoecke Co-developed-by: Franz Schnyder Signed-off-by: Franz Schnyder Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../dts/freescale/imx93-imx91-lino-common.dtsi | 536 +++++++++++++++++++++ .../freescale/imx93-imx91-lino-verdin-common.dtsi | 175 +++++++ .../imx93-imx91-lino-verdin-dev-common.dtsi | 216 +++++++++ .../boot/dts/freescale/imx93-lino-verdin-dev.dts | 24 + arch/arm64/boot/dts/freescale/imx93-lino.dtsi | 359 ++++++++++++++ 6 files changed, 1311 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx93-imx91-lino-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dev-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx93-lino-verdin-dev.dts create mode 100644 arch/arm64/boot/dts/freescale/imx93-lino.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 9971b34f7301..221c56d7845a 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -895,6 +895,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk.dtb imx93-14x14-evk-mqs-dtbs += imx93-14x14-evk.dtb imx9-mqs.dtbo dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-kontron-bl-osm-s.dtb +dtb-$(CONFIG_ARCH_MXC) += imx93-lino-verdin-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-nash.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin.dtb diff --git a/arch/arm64/boot/dts/freescale/imx93-imx91-lino-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-common.dtsi new file mode 100644 index 000000000000..f8f13f785860 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-common.dtsi @@ -0,0 +1,536 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93/iMX91 SoM + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + */ + +#include +#include + +/ { + aliases { + can0 = &flexcan1; + can1 = &flexcan2; + eeprom0 = &som_eeprom; + ethernet0 = &eqos; + ethernet1 = &fec; + i2c0 = &lpi2c2; + i2c1 = &lpi2c1; + i2c2 = &lpi2c3; + i2c3 = &lpi2c4; + mmc0 = &usdhc1; + mmc1 = &usdhc2; + mmc2 = &usdhc3; + serial0 = &lpuart6; + serial1 = &lpuart7; + serial2 = &lpuart1; + serial3 = &lpuart2; + usb0 = &usbotg1; + usb1 = &usbotg2; + }; + + chosen { + stdout-path = &lpuart1; + }; + + /* Lino SD_1 Power Supply */ + reg_sd1_vmmc: regulator-sdhci2-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1_pwr_en>; + /* Lino SD_1_PWR_EN (Lino P72) */ + gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + off-on-delay-us = <100000>; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3_SD"; + startup-delay-us = <20000>; + }; + + reg_sd1_vqmmc: regulator-sdhci2-vqmmc { + compatible = "regulator-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1_vsel>; + /* PMIC_SD_2_VSEL */ + gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "LDO1-VSEL-SD (PMIC)"; + states = <1800000 0x1>, + <3300000 0x0>; + vin-supply = <®_sd_3v3_1v8>; + }; + + reg_usb1_vbus: regulator-usb1-vbus { + compatible = "regulator-fixed"; + /* Lino USB_1_EN (P27) */ + gpios = <&som_gpio_expander 0 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "USB_1_EN"; + startup-delay-us = <20000>; + }; + + reg_usb2_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + /* Lino USB_2_EN (P61) */ + gpios = <&som_gpio_expander 1 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "USB_2_EN"; + startup-delay-us = <20000>; + }; +}; + +/* Lino ADC_1, ADC_2, ADC_3 and ADC_4 */ +&adc1 { + vref-supply = <®_1v8>; +}; + +/* Lino ETH_1 */ +&eqos { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mdio>, <&pinctrl_eth1>; + + mdio: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; +}; + +/* Lino ETH_2 */ +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth2>; +}; + +/* Lino CAN_1 */ +&flexcan1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1>; +}; + +/* Lino CAN_2 */ +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can2>; +}; + +&gpio1 { + gpio-line-names = + "LINO_P18", + "LINO_P16", + "PMIC_I2C_SCL", + "PMIC_I2C_SDA", + "", + "", + "", + "", + "", + "", + "LINO_P65", /* 10 */ + "LINO_S18", + "LINO_S24", + "LINO_S20", + "LINO_S22", + ""; +}; + +&gpio2 { + gpio-line-names = + "LINO_P30", + "LINO_P32", + "LINO_P24", + "LINO_P26", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "LINO_P58", + "", + "", + "", + "", + "LINO_P34", + "", + "", + "", /* 20 */ + "", + "LINO_P36", + "", + "LINO_P38", + "", + "", + "", + "LINO_P20", + "LINO_P22"; +}; + +&gpio3 { + gpio-line-names = + "LINO_P78", + "", + "", + "", + "", + "", + "", + "LINO_P72", + "", + "", + "", /* 10 */ + "", + "", + "", + "", + "", + "", + "", + "", + "PMIC_SD_2_VSEL", + "", /* 20 */ + "", + "", + "", + "", + "", + "LINO_P40", + "LINO_P42", + "", + "", + "", /* 30 */ + ""; +}; + +&gpio4 { + gpio-line-names = + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "", + "", + "LINO_P46", + "LINO_P48", + "", + "", + "", + "", + "", /* 20 */ + "", + "", + "", + "", + "", + "", + "", + "LINO_P44", + "GPIO_EXP_INT#"; +}; + +/* Lino I2C_1 */ +&lpi2c1 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio1 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; +}; + +/* On-module I2C - PMIC_I2C */ +&lpi2c2 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_pmic_i2c>; + pinctrl-1 = <&pinctrl_pmic_i2c_gpio>; + clock-frequency = <400000>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; + + status = "okay"; + + som_gpio_expander: gpio@21 { + compatible = "nxp,pcal6408"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_exp_int>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio4>; + interrupts = <29 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "Lino_P27", /* Lino USB_1_EN */ + "Lino_P61", /* Lino USB_2_EN */ + "TPM_SPI_CS#", + "Lino_P29", /* Lino USB_1_OC# */ + "Lino_P63", /* Lino USB_2_OC# */ + "PMIC_INT#", + "TPM_IRQ#", + "Lino_S66"; + }; + + pmic@32 { + compatible = "nxp,pf9453"; + reg = <0x32>; + interrupt-parent = <&som_gpio_expander>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + + regulators { + BUCK1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + regulator-name = "+V1.1_DDR (PMIC BUCK1)"; + }; + + reg_vdd_soc: BUCK2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <612500>; + regulator-name = "+VDD_SOC (PMIC BUCK2)"; + regulator-ramp-delay = <12500>; + }; + + reg_1v8: BUCK3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V1.8 / +V1.8_ANA (PMIC BUCK3)"; + }; + + reg_3v3: BUCK4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3 (PMIC BUCK4)"; + }; + + reg_sd_3v3_1v8: LDO1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V3.3_1.8_SD (PMIC LDO1)"; + }; + + LDO2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <800000>; + regulator-min-microvolt = <800000>; + regulator-name = "+V0.8_ANA (PMIC LDO2)"; + }; + + LDO-SNVS { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V1.8_BBSM (PMIC LDO-SNVS)"; + }; + }; + }; + + temperature-sensor@48 { + compatible = "ti,tmp1075"; + reg = <0x48>; + }; + + som_eeprom: eeprom@50 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +/* Lino I2C_2 */ +&lpi2c3 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio2 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; +}; + +/* Lino I2C_3 */ +&lpi2c4 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio2 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; +}; + +/* Lino SPI_2 */ +&lpspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi2>, <&pinctrl_spi2_cs0_gpio>; + cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>, <&som_gpio_expander 2 GPIO_ACTIVE_LOW>; + + status = "okay"; + + tpm@1 { + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; + reg = <1>; + interrupt-parent = <&som_gpio_expander>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; + spi-max-frequency = <18500000>; + }; +}; + +/* Lino SPI_1 */ +&lpspi8 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi1>, <&pinctrl_spi1_cs0_gpio>; + cs-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; +}; + +/* Lino UART_3, used as the Linux Console */ +&lpuart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; +}; + +/* Lino UART_4 */ +&lpuart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; +}; + +/* Lino UART_1 */ +&lpuart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + uart-has-rtscts; +}; + +/* Lino UART_2 */ +&lpuart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + uart-has-rtscts; +}; + +/* Lino I2S_1 */ +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s1>; + assigned-clocks = <&clk IMX93_CLK_SAI3>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <24576000>; +}; + +/* Lino PWM_1 */ +&tpm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; +}; + +/* Lino PWM_2 */ +&tpm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; +}; + +/* Lino PWM_3 */ +&tpm6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm3>; +}; + +/* Lino USB_1 */ +&usbotg1 { + dr_mode = "otg"; + adp-disable; + hnp-disable; + srp-disable; + usb-role-switch; + disable-over-current; + role-switch-default-mode = "peripheral"; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; +}; + +/* Lino USB_2 */ +&usbotg2 { + disable-over-current; + dr_mode = "host"; + vbus-supply = <®_usb2_vbus>; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; +}; + +/* On-module eMMC */ +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_emmc>; + pinctrl-1 = <&pinctrl_emmc>; + pinctrl-2 = <&pinctrl_emmc>; + no-sd; + no-sdio; + non-removable; + + status = "okay"; +}; + +/* Lino SD_1 */ +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_sd1>, <&pinctrl_sd1_cd>; + pinctrl-1 = <&pinctrl_sd1>, <&pinctrl_sd1_cd>; + pinctrl-2 = <&pinctrl_sd1>, <&pinctrl_sd1_cd>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + disable-wp; + vmmc-supply = <®_sd1_vmmc>; + vqmmc-supply = <®_sd1_vqmmc>; +}; + +/* Lino SD_2 */ +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_sd2>; + pinctrl-1 = <&pinctrl_sd2>; + pinctrl-2 = <&pinctrl_sd2>; +}; + +&wdog3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-common.dtsi new file mode 100644 index 000000000000..0023e76210ce --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-common.dtsi @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93/iMX91 SoM on Lino-Verdin Adapter + * + * https://www.toradex.com/computer-on-modules/verdin-arm-family + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + */ + +#include +#include + +/ { + verdin_i2s1_mclk: clock-24576000 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24576000>; + }; + + verdin_csi1_mclk: clock-25000000 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + connector { + compatible = "gpio-usb-b-connector", "usb-b-connector"; + id-gpios = <&adapter_gpio_expander 1 GPIO_ACTIVE_HIGH>; + self-powered; + type = "micro"; + vbus-supply = <®_usb1_vbus>; + + port { + usb_1_connector: endpoint { + remote-endpoint = <&usb1_drd_sw>; + }; + }; + }; + + verdin_gpio_keys: gpio-keys { + compatible = "gpio-keys"; + + status = "disabled"; + + key-wakeup { + debounce-interval = <10>; + /* Verdin CTRL_WAKE1_MICO# (SODIMM 252) */ + gpios = <&adapter_gpio_expander 2 GPIO_ACTIVE_LOW>; + label = "Wake-Up"; + wakeup-source; + linux,code = ; + }; + }; +}; + +/* Lino ETH_1 */ +&eqos { + phy-handle = <ðphy1>; + phy-mode = "rgmii-id"; +}; + +/* Lino I2C_1 */ +&lpi2c1 { + status = "okay"; + + i2c-mux@70 { + compatible = "nxp,pca9543"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + verdin_i2c_1: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + adapter_i2c: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + adapter_gpio_expander: gpio@21 { + compatible = "nxp,pcal6416"; + reg = <0x21>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_11>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio1>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "SODIMM_244", /* Verdin PCIE_1_RESET# */ + "SODIMM_161", /* Verdin USB_1_ID */ + "SODIMM_252", /* Verdin CTRL_WAKE1_MICO# */ + "ETH_1_INT#", + "CTRL_EN_WIFI", + "", + "", + "", + "SODIMM_42", /* Verdin I2S_2_BCLK */ + "SODIMM_48", /* Verdin I2S_2_D_IN */ + "SODIMM_46", /* Verdin I2S_2_D_OUT */ + "SODIMM_44", /* Verdin I2S_2_SYNC */ + "SODIMM_64", /* Verdin QSPI_1_CS2# */ + "SODIMM_66", /* Verdin QSPI_1_DQS */ + "SODIMM_60", /* Verdin QSPI_1_IO2 */ + "SODIMM_62"; /* Verdin QSPI_1_IO3 */ + + verdin_pcie_1_reset_hog: pcie-1-reset-hog { + gpio-hog; + /* Verdin PCIE_1_RESET# (SODIMM 244) */ + gpios = <0 GPIO_ACTIVE_LOW>; + line-name = "PCIE_1_RESET#"; + output-low; + + status = "disabled"; + }; + }; + + /* Current measurement into module VCC */ + hwmon@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + }; + }; +}; + +/* Lino UART_1 */ +&lpuart6 { + status = "okay"; + + bluetooth { + compatible = "nxp,88w8987-bt"; + fw-init-baudrate = <3000000>; + }; +}; + +/* Lino Ethernet MDIO */ +&mdio { + status = "okay"; + + ethphy1: ethernet-phy@1 { + reg = <1>; + interrupt-parent = <&adapter_gpio_expander>; + interrupts = <3 IRQ_TYPE_EDGE_FALLING>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + }; +}; + +/* Lino USB_1 */ +&usbotg1 { + port { + usb1_drd_sw: endpoint { + remote-endpoint = <&usb_1_connector>; + }; + }; +}; + +/* Lino SD_2 */ +&usdhc3 { + keep-power-in-suspend; + non-removable; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dev-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dev-common.dtsi new file mode 100644 index 000000000000..1664b380e58e --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dev-common.dtsi @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93/iMX91 SoM on Lino-Verdin Adapter / Development carrier board + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + * https://www.toradex.com/products/carrier-board/verdin-development-board-kit + */ + +/ { + aliases { + eeprom1 = &carrier_eeprom; + }; + + 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 = "verdin-nau8822"; + simple-audio-card,routing = + "Headphones", "LHP", + "Headphones", "RHP", + "Speaker", "LSPK", + "Speaker", "RSPK", + "Line Out", "AUXOUT1", + "Line Out", "AUXOUT2", + "LAUX", "Line In", + "RAUX", "Line In", + "LMICP", "Mic In", + "RMICP", "Mic In"; + simple-audio-card,widgets = + "Headphones", "Headphones", + "Line Out", "Line Out", + "Speaker", "Speaker", + "Microphone", "Mic In", + "Line", "Line In"; + + codec_dai: simple-audio-card,codec { + sound-dai = <&nau8822_1a>; + }; + + simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + }; +}; + +/* Lino ADC_1, ADC_2, ADC_3 and ADC_4 */ +&adc1 { + status = "okay"; +}; + +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>, <&pinctrl_gpio3>, + <&pinctrl_gpio4>, <&pinctrl_gpio5>; +}; + +&gpio3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio6>, <&pinctrl_gpio7>; +}; + +&gpio4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio8>, <&pinctrl_gpio9>, <&pinctrl_gpio10>; +}; + +/* Lino ETH_1 */ +&eqos { + status = "okay"; +}; + +/* Lino ETH_2 */ +&fec { + phy-handle = <ðphy2>; + phy-mode = "rgmii-id"; + + status = "okay"; +}; + +/* Lino CAN_1 */ +&flexcan1 { + status = "okay"; +}; + +/* Lino CAN_2 */ +&flexcan2 { + status = "okay"; +}; + +/* Lino I2C_2 */ +&lpi2c3 { + status = "okay"; +}; + +/* Lino I2C_3 */ +&lpi2c4 { + status = "okay"; +}; + +/* Lino SPI_1 */ +&lpspi8 { + status = "okay"; +}; + +/* Lino UART_3, used as the Linux Console */ +&lpuart1 { + status = "okay"; +}; + +/* Lino UART_4 */ +&lpuart2 { + status = "okay"; +}; + +/* Lino UART_2 */ +&lpuart7 { + status = "okay"; +}; + +/* Lino Ethernet MDIO */ +&mdio { + ethphy2: ethernet-phy@7 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <7>; + micrel,led-mode = <0>; + }; +}; + +/* Lino I2S_1 */ +&sai3 { + status = "okay"; +}; + +/* Lino PWM_1 */ +&tpm4 { + status = "okay"; +}; + +/* Lino PWM_2 */ +&tpm5 { + status = "okay"; +}; + +/* Lino PWM_3 */ +&tpm6 { + status = "okay"; +}; + +/* Lino USB_1 */ +&usbotg1 { + status = "okay"; +}; + +/* Lino USB_2 */ +&usbotg2 { + status = "okay"; +}; + +/* Lino SD_1 */ +&usdhc2 { + status = "okay"; +}; + +/* Verdin CTRL_WAKE1_MICO# */ +&verdin_gpio_keys { + status = "okay"; +}; + +/* Verdin I2C_1 */ +&verdin_i2c_1 { + status = "okay"; + + nau8822_1a: audio-codec@1a { + compatible = "nuvoton,nau8822"; + reg = <0x1a>; + clock-names = "mclk"; + clocks = <&verdin_i2s1_mclk>; + #sound-dai-cells = <0>; + }; + + carrier_gpio_expander: gpio@21 { + compatible = "nxp,pcal6416"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + }; + + /* Current measurement into module VCC */ + hwmon@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + + temperature-sensor@4f { + compatible = "ti,tmp75c"; + reg = <0x4f>; + }; + + carrier_eeprom: eeprom@57 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* Verdin PCIE_1_RESET# */ +&verdin_pcie_1_reset_hog { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-lino-verdin-dev.dts b/arch/arm64/boot/dts/freescale/imx93-lino-verdin-dev.dts new file mode 100644 index 000000000000..a79553d94649 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-lino-verdin-dev.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93 SoM on Lino-Verdin Adapter / Development carrier board + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + * https://www.toradex.com/products/carrier-board/verdin-development-board-kit + */ + +/dts-v1/; + +#include "imx93.dtsi" +#include "imx93-lino.dtsi" +#include "imx93-imx91-lino-verdin-common.dtsi" +#include "imx93-imx91-lino-verdin-dev-common.dtsi" + +/ { + model = "Toradex Lino iMX93 on Verdin Adapter plus Development Board"; + compatible = "toradex,lino-imx93-verdin-dev", + "toradex,lino-imx93-verdin", + "toradex,lino-imx93", + "fsl,imx93"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-lino.dtsi b/arch/arm64/boot/dts/freescale/imx93-lino.dtsi new file mode 100644 index 000000000000..cab7f344f2fe --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-lino.dtsi @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93 SoM + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + */ + +#include "imx93-pinfunc.h" +#include "imx93-imx91-lino-common.dtsi" + +/ { + reserved-memory { + ranges; + #address-cells = <2>; + #size-cells = <2>; + + rsc_table: rsc-table@2021e000 { + reg = <0 0x2021e000 0 0x1000>; + no-map; + }; + + vdev0vring0: vdev0vring0@a4000000 { + reg = <0 0xa4000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@a4008000 { + reg = <0 0xa4008000 0 0x8000>; + no-map; + }; + + vdev1vring0: vdev1vring0@a4010000 { + reg = <0 0xa4010000 0 0x8000>; + no-map; + }; + + vdev1vring1: vdev1vring1@a4018000 { + reg = <0 0xa4018000 0 0x8000>; + no-map; + }; + + vdev0buffer: vdev0buffer@a4020000 { + compatible = "shared-dma-pool"; + reg = <0 0xa4020000 0 0x100000>; + no-map; + }; + }; +}; + +&cm33 { + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu1 0 1>, + <&mu1 1 1>, + <&mu1 3 1>; + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, + <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; + + status = "okay"; +}; + +&mu1 { + status = "okay"; +}; + +&iomuxc { + /* Lino CAN_1 */ + pinctrl_can1: can1grp { + fsl,pins = , /* Lino P12 */ + ; /* Lino P10 */ + }; + + /* Lino CAN_2 */ + pinctrl_can2: can2grp { + fsl,pins = , /* Lino S28 */ + ; /* Lino S30 */ + }; + + /* Lino ETH_1 RGMII */ + pinctrl_eth1: eqosgrp { + fsl,pins = , /* Lino P77 */ + , /* Lino P79 */ + , /* Lino P81 */ + , /* Lino P83 */ + , /* Lino P73 */ + , /* Lino P75 */ + , /* Lino P97 */ + , /* Lino P95 */ + , /* Lino P93 */ + , /* Lino P91 */ + , /* Lino P89 */ + ; /* Lino P85 */ + }; + + /* Lino ETH MDIO */ + pinctrl_mdio: eqosmdiogrp { + fsl,pins = , /* Lino P69 */ + ; /* Lino P67 */ + }; + + /* Lino ETH_2 RGMII */ + pinctrl_eth2: fecgrp { + fsl,pins = , /* Lino S77 */ + , /* Lino S79 */ + , /* Lino S81 */ + , /* Lino S83 */ + , /* Lino S71 */ + , /* Lino S73 */ + , /* Lino S99 */ + , /* Lino S97 */ + , /* Lino S93 */ + , /* Lino S91 */ + , /* Lino S87 */ + ; /* Lino S89 */ + }; + + /* Lino GPIO_11 */ + pinctrl_gpio_11: gpio1io10grp { + fsl,pins = ; /* Lino P65 */ + }; + + /* Lino SPI_2_CS as GPIO */ + pinctrl_spi2_cs0_gpio: gpio1io11grp { + fsl,pins = ; /* Lino S18 */ + }; + + /* Lino GPIO_1 */ + pinctrl_gpio1: gpio2io0grp { + fsl,pins = ; /* Lino P30 */ + }; + + /* Lino GPIO_2 */ + pinctrl_gpio2: gpio2io1grp { + fsl,pins = ; /* Lino P32 */ + }; + + /* Lino SPI_1_CS as GPIO */ + pinctrl_spi1_cs0_gpio: gpio2io12grp { + fsl,pins = ; /* Lino P58 */ + }; + + /* Lino GPIO_3 */ + pinctrl_gpio3: gpio2io17grp { + fsl,pins = ; /* Lino P34 */ + }; + + /* Lino GPIO_4 */ + pinctrl_gpio4: gpio2io22grp { + fsl,pins = ; /* Lino P36 */ + }; + + /* Lino PWM_3 as GPIO */ + pinctrl_pwm3_gpio: gpio2io23grp { + fsl,pins = ; /* Lino P5 */ + }; + + /* Lino GPIO_5 */ + pinctrl_gpio5: gpio2io24grp { + fsl,pins = ; /* Lino P38 */ + }; + + /* Lino GPIO_6 */ + pinctrl_gpio6: gpio3io26grp { + fsl,pins = ; /* Lino P40 */ + }; + + /* Lino GPIO_7 */ + pinctrl_gpio7: gpio3io27grp { + fsl,pins = ; /* Lino P42 */ + }; + + /* Lino GPIO_9 */ + pinctrl_gpio9: gpio4io14grp { + fsl,pins = ; /* Lino P46 */ + }; + + /* Lino GPIO_10 */ + pinctrl_gpio10: gpio4io15grp { + fsl,pins = ; /* Lino P48 */ + }; + + /* Lino GPIO_8 */ + pinctrl_gpio8: gpio4io28grp { + fsl,pins = ; /* Lino P44 */ + }; + + /* On-module GPIO_EXP_INT# */ + pinctrl_gpio_exp_int: gpio4io29grp { + fsl,pins = ; /* GPIO_EXP_INT# */ + }; + + /* Lino I2C_1 as GPIO */ + pinctrl_i2c1_gpio: lpi2c1gpiogrp { + fsl,pins = , /* Lino P18 */ + ; /* Lino P16 */ + }; + + /* Lino I2C_1 */ + pinctrl_i2c1: lpi2c1grp { + fsl,pins = , /* Lino P18 */ + ; /* Lino P16 */ + }; + + /* On-module PMIC I2C as GPIO */ + pinctrl_pmic_i2c_gpio: lpi2c2gpiogrp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* On-module PMIC I2C */ + pinctrl_pmic_i2c: lpi2c2grp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* Lino I2C_2 as GPIO */ + pinctrl_i2c2_gpio: lpi2c3gpiogrp { + fsl,pins = , /* Lino P20 */ + ; /* Lino P22 */ + }; + + /* Lino I2C_2 */ + pinctrl_i2c2: lpi2c3grp { + fsl,pins = , /* Lino P20 */ + ; /* Lino P22 */ + }; + + /* Lino I2C_3 as GPIO */ + pinctrl_i2c3_gpio: lpi2c4gpiogrp { + fsl,pins = , /* Lino P24 */ + ; /* Lino P26 */ + }; + + /* Lino I2C_3 */ + pinctrl_i2c3: lpi2c4grp { + fsl,pins = , /* Lino P24 */ + ; /* Lino P26 */ + }; + + /* Lino SPI_2 */ + pinctrl_spi2: lpspi1grp { + fsl,pins = , /* Lino S20 */ + , /* Lino S22 */ + ; /* Lino S24 */ + }; + + /* Lino SPI_1 */ + pinctrl_spi1: lpspi8grp { + fsl,pins = , /* Lino P54 */ + , /* Lino P56 */ + ; /* Lino P52 */ + }; + + /* Lino UART_3 */ + pinctrl_uart3: lpuart1grp { + fsl,pins = , /* Lino P17 */ + ; /* Lino P19 */ + }; + + /* Lino UART_4 */ + pinctrl_uart4: lpuart2grp { + fsl,pins = , /* Lino P23 */ + ; /* Lino P25 */ + }; + + /* Lino UART_1 */ + pinctrl_uart1: lpuart6grp { + fsl,pins = , /* Lino P11 */ + , /* Lino P9 */ + , /* Lino P8 */ + ; /* Lino P6 */ + }; + + /* Lino UART_2 */ + pinctrl_uart2: lpuart7grp { + fsl,pins = , /* Lino P15 */ + , /* Lino P13 */ + , /* Lino S7 */ + ; /* Lino S5 */ + }; + + /* Lino I2S_1 */ + pinctrl_i2s1: sai3grp { + fsl,pins = , /* Lino S94 */ + , /* Lino S98 */ + , /* Lino S100 */ + ; /* Lino S96 */ + }; + + /* Lino PWM_1 */ + pinctrl_pwm1: tpm4ch1grp { + fsl,pins = ; /* Lino P1 */ + }; + + /* Lino PWM_2 */ + pinctrl_pwm2: tpm5ch2grp { + fsl,pins = ; /* Lino P3 */ + }; + + /* Lino PWM_3 */ + pinctrl_pwm3: tpm6ch1grp { + fsl,pins = ; /* Lino P5 */ + }; + + /* On-module eMMC */ + pinctrl_emmc: usdhc1grp { + fsl,pins = , /* eMMC_CLK */ + , /* eMMC_CMD */ + , /* eMMC_DATA0 */ + , /* eMMC_DATA1 */ + , /* eMMC_DATA2 */ + , /* eMMC_DATA3 */ + , /* eMMC_DATA4 */ + , /* eMMC_DATA5 */ + , /* eMMC_DATA6 */ + , /* eMMC_DATA7 */ + ; /* eMMC_STROBE */ + }; + + /* Lino SD_1_CD# */ + pinctrl_sd1_cd: usdhc2cdgrp { + fsl,pins = ; /* Lino P78 */ + }; + + /* Lino SD_1 */ + pinctrl_sd1: usdhc2grp { + fsl,pins = , /* Lino P68 */ + , /* Lino P66 */ + , /* Lino P74 */ + , /* Lino P76 */ + , /* Lino P60 */ + ; /* Lino P64 */ + }; + + /* Lino SD_1_PWR_EN */ + pinctrl_sd1_pwr_en: usdhc2pwrgrp { + fsl,pins = ; /* Lino P72 */ + }; + + /* On-module PMIC_SD_2_VSEL */ + pinctrl_sd1_vsel: usdhc2vselgrp { + fsl,pins = ; /* PMIC_SD_2_VSEL */ + }; + + /* Lino SD_2 */ + pinctrl_sd2: usdhc3grp { + fsl,pins = , /* Lino S10 */ + , /* Lino S8 */ + , /* Lino S12 */ + , /* Lino S16 */ + , /* Lino S2 */ + ; /* Lino S4 */ + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = ; /* PMIC_WDOG_B */ + }; +}; -- cgit v1.2.3 From b3e94243b499869b7c91aade2224c02cb9ce677c Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:30 +0200 Subject: arm64: dts: freescale: imx93-lino: Add dahlia Add support for Lino iMX93 mated with the Verdin adapter and Dahlia carrier board. Link: https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 Link: https://www.toradex.com/accessories/lino-verdin-adapter Link: https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 1 + .../imx93-imx91-lino-verdin-dahlia-common.dtsi | 198 +++++++++++++++++++++ .../dts/freescale/imx93-lino-verdin-dahlia.dts | 24 +++ 3 files changed, 223 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dahlia-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx93-lino-verdin-dahlia.dts diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 221c56d7845a..83688ee447e4 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -895,6 +895,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk.dtb imx93-14x14-evk-mqs-dtbs += imx93-14x14-evk.dtb imx9-mqs.dtbo dtb-$(CONFIG_ARCH_MXC) += imx93-14x14-evk-mqs.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-kontron-bl-osm-s.dtb +dtb-$(CONFIG_ARCH_MXC) += imx93-lino-verdin-dahlia.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-lino-verdin-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-nash.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin.dtb diff --git a/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dahlia-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dahlia-common.dtsi new file mode 100644 index 000000000000..5f6136204e30 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-imx91-lino-verdin-dahlia-common.dtsi @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93/iMX91 SoM on Lino-Verdin Adapter / Dahlia carrier board + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + * https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit + */ + +/ { + aliases { + eeprom1 = &carrier_eeprom; + }; + + reg_1v8_sw: regulator-1v8-sw { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "On-carrier +V1.8_SW"; + }; + + 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 = "verdin-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"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Line", "Line In Jack"; + + codec_dai: simple-audio-card,codec { + sound-dai = <&wm8904_1a>; + }; + + simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + }; +}; + +/* Lino ADC_1, ADC_2, ADC_3 and ADC_4 */ +&adc1 { + status = "okay"; +}; + +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>, <&pinctrl_gpio3>, + <&pinctrl_gpio4>, <&pinctrl_gpio5>; +}; + +&gpio3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio6>, <&pinctrl_gpio7>; +}; + +&gpio4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio8>, <&pinctrl_gpio9>, <&pinctrl_gpio10>; +}; + +/* Lino ETH_1 */ +&eqos { + status = "okay"; +}; + +/* Lino CAN_1 */ +&flexcan1 { + status = "okay"; +}; + +/* Lino CAN_2 */ +&flexcan2 { + status = "okay"; +}; + +/* Lino I2C_2 */ +&lpi2c3 { + status = "okay"; +}; + +/* Lino I2C_3 */ +&lpi2c4 { + status = "okay"; +}; + +/* Lino SPI_1 */ +&lpspi8 { + status = "okay"; +}; + +/* Lino UART_3, used as the Linux Console */ +&lpuart1 { + status = "okay"; +}; + +/* Lino UART_4 */ +&lpuart2 { + status = "okay"; +}; + +/* Lino UART_2 */ +&lpuart7 { + status = "okay"; +}; + +/* Lino I2S_1 */ +&sai3 { + status = "okay"; +}; + +/* Lino PWM_1 */ +&tpm4 { + status = "okay"; +}; + +/* Lino PWM_2 */ +&tpm5 { + status = "okay"; +}; + +/* Lino PWM_3 */ +&tpm6 { + status = "okay"; +}; + +/* Lino USB_1 */ +&usbotg1 { + status = "okay"; +}; + +/* Lino USB_2 */ +&usbotg2 { + status = "okay"; +}; + +/* Lino SD_1 */ +&usdhc2 { + status = "okay"; +}; + +/* Verdin CTRL_WAKE1_MICO# */ +&verdin_gpio_keys { + status = "okay"; +}; + +/* Verdin I2C_1 */ +&verdin_i2c_1 { + status = "okay"; + + wm8904_1a: audio-codec@1a { + compatible = "wlf,wm8904"; + reg = <0x1a>; + clock-names = "mclk"; + clocks = <&verdin_i2s1_mclk>; + #sound-dai-cells = <0>; + AVDD-supply = <®_1v8_sw>; + CPVDD-supply = <®_1v8_sw>; + DBVDD-supply = <®_1v8_sw>; + DCVDD-supply = <®_1v8_sw>; + MICVDD-supply = <®_1v8_sw>; + }; + + /* Current measurement into module VCC */ + hwmon@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + + temperature-sensor@4f { + compatible = "ti,tmp75c"; + reg = <0x4f>; + }; + + carrier_eeprom: eeprom@57 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* Verdin PCIE_1_RESET# */ +&verdin_pcie_1_reset_hog { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-lino-verdin-dahlia.dts b/arch/arm64/boot/dts/freescale/imx93-lino-verdin-dahlia.dts new file mode 100644 index 000000000000..c708a2e18c90 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-lino-verdin-dahlia.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX93 SoM on Lino-Verdin Adapter / Dahlia carrier board + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx93 + * https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit + */ + +/dts-v1/; + +#include "imx93.dtsi" +#include "imx93-lino.dtsi" +#include "imx93-imx91-lino-verdin-common.dtsi" +#include "imx93-imx91-lino-verdin-dahlia-common.dtsi" + +/ { + model = "Toradex Lino iMX93 on Verdin Adapter plus Dahlia Board"; + compatible = "toradex,lino-imx93-verdin-dahlia", + "toradex,lino-imx93-verdin", + "toradex,lino-imx93", + "fsl,imx93"; +}; -- cgit v1.2.3 From a1dea6c558ebe2bfcf905f51b81c08cd398121f8 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:31 +0200 Subject: arm64: dts: freescale: Add Lino iMX91 Add support for the Lino iMX91 SoM, its Verdin adapter, dahlia and development carrier board. Link: https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 Link: https://www.toradex.com/accessories/lino-verdin-adapter Link: https://www.toradex.com/products/carrier-board/verdin-development-board-kit Link: https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 2 + .../dts/freescale/imx91-lino-verdin-dahlia.dts | 24 ++ .../boot/dts/freescale/imx91-lino-verdin-dev.dts | 24 ++ arch/arm64/boot/dts/freescale/imx91-lino.dtsi | 305 +++++++++++++++++++++ 4 files changed, 355 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx91-lino-verdin-dahlia.dts create mode 100644 arch/arm64/boot/dts/freescale/imx91-lino-verdin-dev.dts create mode 100644 arch/arm64/boot/dts/freescale/imx91-lino.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 83688ee447e4..1c4aa73443ba 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -851,6 +851,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-frdm.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-frdm-s.dtb imx91-11x11-evk-mqs-dtbs += imx91-11x11-evk.dtb imx9-mqs.dtbo dtb-$(CONFIG_ARCH_MXC) += imx91-11x11-evk-mqs.dtb +dtb-$(CONFIG_ARCH_MXC) += imx91-lino-verdin-dahlia.dtb +dtb-$(CONFIG_ARCH_MXC) += imx91-lino-verdin-dev.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-phyboard-segin.dtb imx91-9x9-qsb-can1-dtbs += imx91-9x9-qsb.dtb imx91-9x9-qsb-can1.dtbo diff --git a/arch/arm64/boot/dts/freescale/imx91-lino-verdin-dahlia.dts b/arch/arm64/boot/dts/freescale/imx91-lino-verdin-dahlia.dts new file mode 100644 index 000000000000..eb3a8cdcd08f --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx91-lino-verdin-dahlia.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX91 SoM on Lino-Verdin Adapter / Dahlia carrier board + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + * https://www.toradex.com/products/carrier-board/dahlia-carrier-board-kit + */ + +/dts-v1/; + +#include "imx91.dtsi" +#include "imx91-lino.dtsi" +#include "imx93-imx91-lino-verdin-common.dtsi" +#include "imx93-imx91-lino-verdin-dahlia-common.dtsi" + +/ { + model = "Toradex Lino iMX91 on Verdin Adapter plus Dahlia Board"; + compatible = "toradex,lino-imx91-verdin-dahlia", + "toradex,lino-imx91-verdin", + "toradex,lino-imx91", + "fsl,imx91"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx91-lino-verdin-dev.dts b/arch/arm64/boot/dts/freescale/imx91-lino-verdin-dev.dts new file mode 100644 index 000000000000..a988897f3388 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx91-lino-verdin-dev.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX91 SoM on Lino-Verdin Adapter / Development carrier board + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + * https://www.toradex.com/products/carrier-board/verdin-development-board-kit + */ + +/dts-v1/; + +#include "imx91.dtsi" +#include "imx91-lino.dtsi" +#include "imx93-imx91-lino-verdin-common.dtsi" +#include "imx93-imx91-lino-verdin-dev-common.dtsi" + +/ { + model = "Toradex Lino iMX91 on Verdin Adapter plus Development Board"; + compatible = "toradex,lino-imx91-verdin-dev", + "toradex,lino-imx91-verdin", + "toradex,lino-imx91", + "fsl,imx91"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx91-lino.dtsi b/arch/arm64/boot/dts/freescale/imx91-lino.dtsi new file mode 100644 index 000000000000..99d95694e910 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx91-lino.dtsi @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Lino iMX91 SoM + * + * https://www.toradex.com/computer-on-modules/lino-arm-family/nxp-imx91 + */ + +#include "imx91-pinfunc.h" +#include "imx93-imx91-lino-common.dtsi" + +&iomuxc { + /* Lino CAN_1 */ + pinctrl_can1: can1grp { + fsl,pins = , /* Lino P12 */ + ; /* Lino P10 */ + }; + + /* Lino CAN_2 */ + pinctrl_can2: can2grp { + fsl,pins = , /* Lino S28 */ + ; /* Lino S30 */ + }; + + /* Lino ETH_1 RGMII */ + pinctrl_eth1: eqosgrp { + fsl,pins = , /* Lino P77 */ + , /* Lino P79 */ + , /* Lino P81 */ + , /* Lino P83 */ + , /* Lino P73 */ + , /* Lino P75 */ + , /* Lino P97 */ + , /* Lino P95 */ + , /* Lino P93 */ + , /* Lino P91 */ + , /* Lino P89 */ + ; /* Lino P85 */ + }; + + /* Lino ETH MDIO */ + pinctrl_mdio: eqosmdiogrp { + fsl,pins = , /* Lino P69 */ + ; /* Lino P67 */ + }; + + /* Lino ETH_2 RGMII */ + pinctrl_eth2: fecgrp { + fsl,pins = , /* Lino S77 */ + , /* Lino S79 */ + , /* Lino S81 */ + , /* Lino S83 */ + , /* Lino S71 */ + , /* Lino S73 */ + , /* Lino S99 */ + , /* Lino S97 */ + , /* Lino S93 */ + , /* Lino S91 */ + , /* Lino S87 */ + ; /* Lino S89 */ + }; + + /* Lino GPIO_11 */ + pinctrl_gpio_11: gpio1io10grp { + fsl,pins = ; /* Lino P65 */ + }; + + /* Lino SPI_2_CS as GPIO */ + pinctrl_spi2_cs0_gpio: gpio1io11grp { + fsl,pins = ; /* Lino S18 */ + }; + + /* Lino GPIO_1 */ + pinctrl_gpio1: gpio2io0grp { + fsl,pins = ; /* Lino P30 */ + }; + + /* Lino GPIO_2 */ + pinctrl_gpio2: gpio2io1grp { + fsl,pins = ; /* Lino P32 */ + }; + + /* Lino SPI_1_CS as GPIO */ + pinctrl_spi1_cs0_gpio: gpio2io12grp { + fsl,pins = ; /* Lino P58 */ + }; + + /* Lino GPIO_3 */ + pinctrl_gpio3: gpio2io17grp { + fsl,pins = ; /* Lino P34 */ + }; + + /* Lino GPIO_4 */ + pinctrl_gpio4: gpio2io22grp { + fsl,pins = ; /* Lino P36 */ + }; + + /* Lino PWM_3 as GPIO */ + pinctrl_pwm3_gpio: gpio2io23grp { + fsl,pins = ; /* Lino P5 */ + }; + + /* Lino GPIO_5 */ + pinctrl_gpio5: gpio2io24grp { + fsl,pins = ; /* Lino P38 */ + }; + + /* Lino GPIO_6 */ + pinctrl_gpio6: gpio3io26grp { + fsl,pins = ; /* Lino P40 */ + }; + + /* Lino GPIO_7 */ + pinctrl_gpio7: gpio3io27grp { + fsl,pins = ; /* Lino P42 */ + }; + + /* Lino GPIO_9 */ + pinctrl_gpio9: gpio4io14grp { + fsl,pins = ; /* Lino P46 */ + }; + + /* Lino GPIO_10 */ + pinctrl_gpio10: gpio4io15grp { + fsl,pins = ; /* Lino P48 */ + }; + + /* Lino GPIO_8 */ + pinctrl_gpio8: gpio4io28grp { + fsl,pins = ; /* Lino P44 */ + }; + + /* On-module GPIO_EXP_INT# */ + pinctrl_gpio_exp_int: gpio4io29grp { + fsl,pins = ; /* GPIO_EXP_INT# */ + }; + + /* Lino I2C_1 as GPIO */ + pinctrl_i2c1_gpio: lpi2c1gpiogrp { + fsl,pins = , /* Lino P18 */ + ; /* Lino P16 */ + }; + + /* Lino I2C_1 */ + pinctrl_i2c1: lpi2c1grp { + fsl,pins = , /* Lino P18 */ + ; /* Lino P16 */ + }; + + /* On-module PMIC I2C as GPIO */ + pinctrl_pmic_i2c_gpio: lpi2c2gpiogrp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* On-module PMIC I2C */ + pinctrl_pmic_i2c: lpi2c2grp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* Lino I2C_2 as GPIO */ + pinctrl_i2c2_gpio: lpi2c3gpiogrp { + fsl,pins = , /* Lino P20 */ + ; /* Lino P22 */ + }; + + /* Lino I2C_2 */ + pinctrl_i2c2: lpi2c3grp { + fsl,pins = , /* Lino P20 */ + ; /* Lino P22 */ + }; + + /* Lino I2C_3 as GPIO */ + pinctrl_i2c3_gpio: lpi2c4gpiogrp { + fsl,pins = , /* Lino P24 */ + ; /* Lino P26 */ + }; + + /* Lino I2C_3 */ + pinctrl_i2c3: lpi2c4grp { + fsl,pins = , /* Lino P24 */ + ; /* Lino P26 */ + }; + + /* Lino SPI_2 */ + pinctrl_spi2: lpspi1grp { + fsl,pins = , /* Lino S20 */ + , /* Lino S22 */ + ; /* Lino S24 */ + }; + + /* Lino SPI_1 */ + pinctrl_spi1: lpspi8grp { + fsl,pins = , /* Lino P54 */ + , /* Lino P56 */ + ; /* Lino P52 */ + }; + + /* Lino UART_3 */ + pinctrl_uart3: lpuart1grp { + fsl,pins = , /* Lino P17 */ + ; /* Lino P19 */ + }; + + /* Lino UART_4 */ + pinctrl_uart4: lpuart2grp { + fsl,pins = , /* Lino P23 */ + ; /* Lino P25 */ + }; + + /* Lino UART_1 */ + pinctrl_uart1: lpuart6grp { + fsl,pins = , /* Lino P11 */ + , /* Lino P9 */ + , /* Lino P8 */ + ; /* Lino P6 */ + }; + + /* Lino UART_2 */ + pinctrl_uart2: lpuart7grp { + fsl,pins = , /* Lino P15 */ + , /* Lino P13 */ + , /* Lino S7 */ + ; /* Lino S5 */ + }; + + /* Lino I2S_1 */ + pinctrl_i2s1: sai3grp { + fsl,pins = , /* Lino S94 */ + , /* Lino S98 */ + , /* Lino S100 */ + ; /* Lino S96 */ + }; + + /* Lino PWM_1 */ + pinctrl_pwm1: tpm4ch1grp { + fsl,pins = ; /* Lino P1 */ + }; + + /* Lino PWM_2 */ + pinctrl_pwm2: tpm5ch2grp { + fsl,pins = ; /* Lino P3 */ + }; + + /* Lino PWM_3 */ + pinctrl_pwm3: tpm6ch1grp { + fsl,pins = ; /* Lino P5 */ + }; + + /* On-module eMMC */ + pinctrl_emmc: usdhc1grp { + fsl,pins = , /* eMMC_CLK */ + , /* eMMC_CMD */ + , /* eMMC_DATA0 */ + , /* eMMC_DATA1 */ + , /* eMMC_DATA2 */ + , /* eMMC_DATA3 */ + , /* eMMC_DATA4 */ + , /* eMMC_DATA5 */ + , /* eMMC_DATA6 */ + , /* eMMC_DATA7 */ + ; /* eMMC_STROBE */ + }; + + /* Lino SD_1_CD# */ + pinctrl_sd1_cd: usdhc2cdgrp { + fsl,pins = ; /* Lino P78 */ + }; + + /* Lino SD_1 */ + pinctrl_sd1: usdhc2grp { + fsl,pins = , /* Lino P68 */ + , /* Lino P66 */ + , /* Lino P74 */ + , /* Lino P76 */ + , /* Lino P60 */ + ; /* Lino P64 */ + }; + + /* Lino SD_1_PWR_EN */ + pinctrl_sd1_pwr_en: usdhc2pwrgrp { + fsl,pins = ; /* Lino P72 */ + }; + + /* On-module PMIC_SD_2_VSEL */ + pinctrl_sd1_vsel: usdhc2vselgrp { + fsl,pins = ; /* PMIC_SD_2_VSEL */ + }; + + /* Lino SD_2 */ + pinctrl_sd2: usdhc3grp { + fsl,pins = , /* Lino S10 */ + , /* Lino S8 */ + , /* Lino S12 */ + , /* Lino S16 */ + , /* Lino S2 */ + ; /* Lino S4 */ + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = ; /* PMIC_WDOG_B */ + }; +}; -- cgit v1.2.3 From e8a8c86875f4f636bee56b9ba923ba44aee9e640 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:32 +0200 Subject: arm64: dts: freescale: Add Toradex OSM iMX93 Add support for the Toradex OSM iMX93 and its development carrier board. The SoM is available in two variants, with i.MX91 or i.MX93 SoC, using the same PCB (the two chips are pin to pin compatible), to avoid duplication create a common dtsi to share commonalities. Link: https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx93 Link: https://www.toradex.com/products/carrier-board/osm-development-board Co-developed-by: Antoine Gouby Signed-off-by: Antoine Gouby Co-developed-by: Ernest Van Hoecke Signed-off-by: Ernest Van Hoecke Co-developed-by: Franz Schnyder Signed-off-by: Franz Schnyder Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 2 + .../freescale/imx93-imx91-toradex-osm-common.dtsi | 526 +++++++++++++++++++++ .../imx93-imx91-toradex-osm-dev-common.dtsi | 324 +++++++++++++ .../boot/dts/freescale/imx93-toradex-osm-dev.dts | 22 + .../boot/dts/freescale/imx93-toradex-osm.dtsi | 357 ++++++++++++++ 5 files changed, 1231 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-dev-common.dtsi create mode 100644 arch/arm64/boot/dts/freescale/imx93-toradex-osm-dev.dts create mode 100644 arch/arm64/boot/dts/freescale/imx93-toradex-osm.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 1c4aa73443ba..5aaaf99057fa 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -919,6 +919,8 @@ dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin-peb-eval-01.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phyboard-segin-peb-wlbt-05.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-phycore-rpmsg.dtb +dtb-$(CONFIG_ARCH_MXC) += imx93-toradex-osm-dev.dtb + dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba91xxca.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxca.dtb dtb-$(CONFIG_ARCH_MXC) += imx93-tqma9352-mba93xxla.dtb diff --git a/arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-common.dtsi new file mode 100644 index 000000000000..8b0131d4e6e2 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-common.dtsi @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX93/iMX91 SoM + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx93 + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx91 + */ + +#include +#include + +/ { + aliases { + can0 = &flexcan1; + can1 = &flexcan2; + eeprom0 = &som_eeprom; + ethernet0 = &eqos; + ethernet1 = &fec; + i2c0 = &lpi2c2; + i2c1 = &lpi2c3; + i2c2 = &lpi2c1; + mmc0 = &usdhc1; + mmc1 = &usdhc2; + mmc2 = &usdhc3; + rtc0 = &rtc_i2c; + rtc1 = &bbnsm_rtc; + serial0 = &lpuart1; + serial1 = &lpuart6; + serial2 = &lpuart7; + serial3 = &lpuart2; + usb0 = &usbotg1; + usb1 = &usbotg2; + }; + + chosen { + stdout-path = &lpuart1; + }; + + reg_sdio_a_vmmc: regulator-sdhci2-vmmc { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdio_a_pwr_en>; + /* OSM SDIO_A_PWR_EN (OSM D21) */ + gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + off-on-delay-us = <100000>; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "SDIO_A_PWR_EN"; + startup-delay-us = <20000>; + }; + + reg_sdio_a_vqmmc: regulator-sdhci2-vqmmc { + compatible = "regulator-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdio_a_vsel>; + /* PMIC_SD_2_VSEL */ + gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "LDO1-VSEL-SD (PMIC)"; + states = <1800000 0x1>, + <3300000 0x0>; + vin-supply = <®_sd_3v3_1v8>; + }; + + reg_usb_b_vbus: regulator-usb2-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_b_en>; + /* OSM USB_B_EN (OSM AC20) */ + gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "USB_B_EN"; + startup-delay-us = <20000>; + }; +}; + +/* OSM ADC_0, ADC_1 */ +&adc1 { + vref-supply = <®_1v8>; +}; + +/* OSM ETH_A */ +&eqos { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mdio>, <&pinctrl_eth_a>; + + mdio: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; +}; + +/* OSM ETH_B */ +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth_b>; +}; + +/* OSM CAN_A */ +&flexcan1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can_a>; +}; + +/* OSM CAN_B */ +&flexcan2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can_b>; +}; + +&gpio1 { + gpio-line-names = + "OSM_AA20", + "OSM_AA21", + "PMIC_I2C_SCL", + "PMIC_I2C_SDA", + "", + "", + "", + "", + "", + "", + "OSM_AC20", /* 10 */ + "OSM_AA23", + "", + "", + "", + ""; +}; + +&gpio2 { + gpio-line-names = + "OSM_D17", + "OSM_E17", + "OSM_F17", + "OSM_G17", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "OSM_Y15", + "", + "", + "", + "", + "", + "", + "", + "", /* 20 */ + "", + "OSM_H17", + "", + "OSM_J17", + "", + "", + "", + "OSM_AA16", + "OSM_AA15"; +}; + +&gpio3 { + gpio-line-names = + "OSM_J21", + "", + "", + "", + "", + "", + "", + "OSM_D21", + "", + "", + "", /* 10 */ + "", + "", + "", + "", + "", + "", + "", + "", + "PMIC_SD_2_VSEL", + "", /* 20 */ + "", + "", + "", + "", + "", + "", + "CTRL_INT#", + "", + "", + "", /* 30 */ + ""; +}; + +&gpio4 { + gpio-line-names = + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", /* 10 */ + "", + "", + "", + "OSM_K17", + "OSM_L17", + "", + "", + "", + "", + "", /* 20 */ + "", + "", + "", + "", + "", + "", + "", + "OSM_AC16", + "OSM_AC15"; +}; + +/* OSM I2C_B */ +&lpi2c1 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c_b>; + pinctrl-1 = <&pinctrl_i2c_b_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio1 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; + + status = "okay"; + + rtc_i2c: rtc@32 { + compatible = "epson,rx8130"; + reg = <0x32>; + }; +}; + +/* On-module I2C - PMIC_I2C */ +&lpi2c2 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_pmic_i2c>, <&pinctrl_ctrl_int>; + pinctrl-1 = <&pinctrl_pmic_i2c_gpio>, <&pinctrl_ctrl_int>; + clock-frequency = <400000>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; + + status = "okay"; + + som_gpio_expander: gpio@21 { + compatible = "nxp,pcal6416"; + reg = <0x21>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&gpio3>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "OSM_D19", /* OSM GPIO_B_0 */ + "OSM_E19", /* OSM GPIO_B_1 */ + "OSM_F19", /* OSM GPIO_B_2 */ + "OSM_G19", /* OSM GPIO_B_3 */ + "OSM_H19", /* OSM GPIO_B_4 */ + "OSM_J19", /* OSM GPIO_B_5 */ + "OSM_K19", /* OSM GPIO_B_6 */ + "OSM_L19", /* OSM GPIO_B_7 */ + "OSM_D3", /* OSM GPIO_C_0 */ + "OSM_D4", /* OSM GPIO_C_1 */ + "OSM_E3", /* OSM GPIO_C_2/CAM_B_PWR */ + "OSM_E4", /* OSM GPIO_C_3/CAM_B_RST# */ + "OSM_F3", /* OSM GPIO_C_4/DISP_VDD_EN */ + "OSM_F4", /* OSM GPIO_C_5/DISP_BL_EN */ + "OSM_G3", /* OSM GPIO_C_6/CAM_A_PWR */ + "OSM_G4"; /* OSM GPIO_C_7/CAM_A_RST# */ + }; + + tpm@2e { + compatible = "st,st33ktpm2xi2c", "tcg,tpm-tis-i2c"; + reg = <0x2e>; + }; + + pmic@32 { + compatible = "nxp,pf9453"; + reg = <0x32>; + interrupt-parent = <&gpio3>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + + regulators { + BUCK1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + regulator-name = "+V1.1_DDR (PMIC BUCK1)"; + }; + + reg_vdd_soc: BUCK2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <950000>; + regulator-min-microvolt = <612500>; + regulator-name = "+VDD_SOC (PMIC BUCK2)"; + regulator-ramp-delay = <12500>; + }; + + reg_1v8: BUCK3 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V1.8 / +V1.8_ANA (PMIC BUCK3)"; + }; + + reg_3v3: BUCK4 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "+V3.3 (PMIC BUCK4)"; + }; + + reg_sd_3v3_1v8: LDO1 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V3.3_1.8_SD (PMIC LDO1)"; + }; + + LDO2 { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <800000>; + regulator-min-microvolt = <800000>; + regulator-name = "+V0.8_ANA (PMIC LDO2)"; + }; + + LDO-SNVS { + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "+V1.8_BBSM (PMIC LDO-SNVS)"; + }; + }; + }; + + temperature-sensor@48 { + compatible = "ti,tmp1075"; + reg = <0x48>; + }; + + som_eeprom: eeprom@50 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +/* OSM I2C_A */ +&lpi2c3 { + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c_a>; + pinctrl-1 = <&pinctrl_i2c_a_gpio>; + clock-frequency = <100000>; + scl-gpios = <&gpio2 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio2 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + single-master; +}; + +/* OSM SPI_B */ +&lpspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi_b>, <&pinctrl_spi_b_cs0_gpio>; + cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; +}; + +/* OSM SPI_A */ +&lpspi8 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi_a>, <&pinctrl_spi_a_cs0_gpio>; + cs-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; +}; + +/* OSM UART_CON, used as the Linux Console */ +&lpuart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_con>; +}; + +/* OSM UART_C */ +&lpuart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_c>; +}; + +/* OSM UART_A */ +&lpuart6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_a>; + uart-has-rtscts; +}; + +/* OSM UART_B */ +&lpuart7 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart_b>; + uart-has-rtscts; +}; + +/* OSM I2S_A */ +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s_a>; + assigned-clocks = <&clk IMX93_CLK_SAI3>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; +}; + +/* OSM PWM_0 */ +&tpm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0>; +}; + +/* OSM PWM_1 */ +&tpm5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; +}; + +/* OSM PWM_2 */ +&tpm6 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; +}; + +/* OSM USB_A */ +&usbotg1 { + dr_mode = "otg"; + adp-disable; + hnp-disable; + srp-disable; + usb-role-switch; + disable-over-current; + role-switch-default-mode = "peripheral"; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; +}; + +/* OSM USB_B */ +&usbotg2 { + disable-over-current; + dr_mode = "host"; + vbus-supply = <®_usb_b_vbus>; + samsung,picophy-dc-vol-level-adjust = <7>; + samsung,picophy-pre-emp-curr-control = <3>; +}; + +/* On-module eMMC */ +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_emmc>; + pinctrl-1 = <&pinctrl_emmc>; + pinctrl-2 = <&pinctrl_emmc>; + no-sd; + no-sdio; + non-removable; + + status = "okay"; +}; + +/* OSM SDIO_A */ +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_sdio_a>, <&pinctrl_sdio_a_cd>; + pinctrl-1 = <&pinctrl_sdio_a>, <&pinctrl_sdio_a_cd>; + pinctrl-2 = <&pinctrl_sdio_a>, <&pinctrl_sdio_a_cd>; + cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + disable-wp; + vmmc-supply = <®_sdio_a_vmmc>; + vqmmc-supply = <®_sdio_a_vqmmc>; +}; + +/* OSM SDIO_B */ +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_sdio_b>; + pinctrl-1 = <&pinctrl_sdio_b>; + pinctrl-2 = <&pinctrl_sdio_b>; + disable-wp; +}; + +&wdog3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-dev-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-dev-common.dtsi new file mode 100644 index 000000000000..566671b32308 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-imx91-toradex-osm-dev-common.dtsi @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX93/iMX91 SoM on OSM Development carrier board + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx93 + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx91 + * https://www.toradex.com/products/carrier-board/osm-development-board + */ + +#include +#include +#include + +/ { + aliases { + eeprom1 = &carrier_eeprom; + }; + + reg_carrier_1p8v: regulator-carrier-1p8v { + compatible = "regulator-fixed"; + regulator-max-microvolt = <1800000>; + regulator-min-microvolt = <1800000>; + regulator-name = "On-carrier V1.8_SW"; + }; + + 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 = "verdin-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"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Line", "Line In Jack"; + + codec_dai: simple-audio-card,codec { + sound-dai = <&wm8904_1a>; + }; + + simple-audio-card,cpu { + sound-dai = <&sai3>; + }; + }; +}; + +/* OSM ADC_0, ADC_1 */ +&adc1 { + status = "okay"; +}; + +/* OSM ETH_A */ +&eqos { + phy-handle = <ðphy_a>; + phy-mode = "rgmii-id"; + + status = "okay"; +}; + +/* OSM ETH_B */ +&fec { + phy-handle = <ðphy_b>; + phy-mode = "rgmii-id"; + + status = "okay"; +}; + +/* OSM CAN_A */ +&flexcan1 { + status = "okay"; +}; + +/* OSM CAN_B */ +&flexcan2 { + status = "okay"; +}; + +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a1>, <&pinctrl_gpio_a2>, <&pinctrl_gpio_a3>, + <&pinctrl_gpio_a4>, <&pinctrl_gpio_a5>; +}; + +&gpio4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a6>; +}; + +/* OSM I2C_B */ +&lpi2c1 { + i2c-mux@70 { + compatible = "nxp,pca9548"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + + i2c_csi: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c_lvds: i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + /* I2C on DSI connector pin #4 and #6 */ + i2c_dsi_1: i2c@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + /* I2C on DSI connector pin #52 and #54 */ + i2c_dsi_2: i2c@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +/* OSM I2C_A */ +&lpi2c3 { + status = "okay"; + + wm8904_1a: audio-codec@1a { + compatible = "wlf,wm8904"; + reg = <0x1a>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s_a_mclk>; + clocks = <&clk IMX93_CLK_SAI3>; + 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>; + }; + + gpio@20 { + compatible = "nxp,pcal6408"; + reg = <0x20>; + #gpio-cells = <2>; + gpio-controller; + gpio-line-names = + "PWR_CTRL_CAN_A", /* 0 */ + "PWR_CTRL_CAN_B", + "PWR_CTRL_USB-HUB", + "LVDS_MUX_CTRL", + "USB_MUX_CTRL", + "I2CA_IOEXP_P5", + "I2CA_IOEXP_P6", + "I2CA_IOEXP_P7"; + + lvds_mux_ctrl: lvds-mux-ctrl-hog { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; + line-name = "LVDS_MUX_CTRL"; + output-high; + }; + + usb_mux_ctrl: usb-mux-ctrl-hog { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + line-name = "USB_MUX_CTRL"; + output-low; + }; + }; + + hwmon@40 { + compatible = "ti,ina219"; + reg = <0x40>; + shunt-resistor = <10000>; + }; + + temperature-sensor@4f { + compatible = "ti,tmp1075"; + reg = <0x4f>; + }; + + tcpc@52 { + compatible = "nxp,ptn5110", "tcpci"; + reg = <0x52>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a0>; + interrupt-parent = <&gpio2>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + connector { + compatible = "usb-c-connector"; + label = "USB_A"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + self-powered; + source-pdos = ; + sink-pdos = ; + op-sink-microwatt = <0>; + + port { + usb_c_a_conn_hs: endpoint { + remote-endpoint = <&usb_a_hs>; + }; + }; + }; + }; + + carrier_eeprom: eeprom@57 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x57>; + pagesize = <16>; + }; +}; + +/* OSM SPI_B */ +&lpspi1 { + status = "okay"; +}; + +/* OSM SPI_A */ +&lpspi8 { + status = "okay"; +}; + +/* OSM UART_CON, used as the Linux Console */ +&lpuart1 { + status = "okay"; +}; + +/* OSM UART_C */ +&lpuart2 { + status = "okay"; +}; + +/* OSM UART_A */ +&lpuart6 { + status = "okay"; +}; + +/* OSM UART_B */ +&lpuart7 { + status = "okay"; +}; + +/* OSM ETH_MDIO */ +&mdio { + status = "okay"; + + ethphy_a: ethernet-phy@2 { + reg = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_a7>; + interrupt-parent = <&gpio4>; + interrupts = <15 IRQ_TYPE_LEVEL_LOW>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + }; + + ethphy_b: ethernet-phy@3 { + reg = <3>; + ti,rx-internal-delay = ; + ti,tx-internal-delay = ; + }; +}; + +/* OSM I2S_A */ +&sai3 { + status = "okay"; +}; + +/* OSM PWM_0 */ +&tpm4 { + status = "okay"; +}; + +/* OSM PWM_1 */ +&tpm5 { + status = "okay"; +}; + +/* OSM PWM_2 */ +&tpm6 { + status = "okay"; +}; + +/* OSM USB_A */ +&usbotg1 { + status = "okay"; + + port { + usb_a_hs: endpoint { + remote-endpoint = <&usb_c_a_conn_hs>; + }; + }; +}; + +/* OSM USB_B */ +&usbotg2 { + status = "okay"; +}; + +/* OSM SDIO_A */ +&usdhc2 { + status = "okay"; +}; + +/* OSM SDIO_B */ +&usdhc3 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-toradex-osm-dev.dts b/arch/arm64/boot/dts/freescale/imx93-toradex-osm-dev.dts new file mode 100644 index 000000000000..a6cc2ae35d04 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-toradex-osm-dev.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX93 SoM on OSM Development carrier board + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx93 + * https://www.toradex.com/products/carrier-board/osm-development-board + */ + +/dts-v1/; + +#include "imx93.dtsi" +#include "imx93-toradex-osm.dtsi" +#include "imx93-imx91-toradex-osm-dev-common.dtsi" + +/ { + model = "Toradex OSM iMX93 on OSM Development Board"; + compatible = "toradex,osm-imx93-dev", + "toradex,osm-imx93", + "fsl,imx93"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx93-toradex-osm.dtsi b/arch/arm64/boot/dts/freescale/imx93-toradex-osm.dtsi new file mode 100644 index 000000000000..ea5e6055e3f5 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx93-toradex-osm.dtsi @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX93 SoM + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx93 + */ + +#include "imx93-pinfunc.h" +#include "imx93-imx91-toradex-osm-common.dtsi" + +/ { + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + rsc_table: rsc-table@2021e000 { + reg = <0 0x2021e000 0 0x1000>; + no-map; + }; + + vdev0vring0: vdev0vring0@a4000000 { + reg = <0 0xa4000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@a4008000 { + reg = <0 0xa4008000 0 0x8000>; + no-map; + }; + + vdev1vring0: vdev1vring0@a4010000 { + reg = <0 0xa4010000 0 0x8000>; + no-map; + }; + + vdev1vring1: vdev1vring1@a4018000 { + reg = <0 0xa4018000 0 0x8000>; + no-map; + }; + + vdev0buffer: vdev0buffer@a4020000 { + compatible = "shared-dma-pool"; + reg = <0 0xa4020000 0 0x100000>; + no-map; + }; + }; +}; + +&cm33 { + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu1 0 1>, + <&mu1 1 1>, + <&mu1 3 1>; + memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, + <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; + + status = "okay"; +}; + +&mu1 { + status = "okay"; +}; + +&iomuxc { + /* OSM CAN_A */ + pinctrl_can_a: can1grp { + fsl,pins = , /* OSM AB17 */ + ; /* OSM AC17 */ + }; + + /* OSM CAN_B */ + pinctrl_can_b: can2grp { + fsl,pins = , /* OSM AC19 */ + ; /* OSM AB19 */ + }; + + /* OSM CAM_MCK */ + pinctrl_cam_mck: ccmclk1grp { + fsl,pins = ; /* OSM C2 */ + }; + + /* OSM ETH_A RGMII */ + pinctrl_eth_a: eqosgrp { + fsl,pins = , /* OSM K15 */ + , /* OSM L15 */ + , /* OSM N15 */ + , /* OSM P15 */ + , /* OSM R15 */ + , /* OSM M15 */ + , /* OSM H15 */ + , /* OSM G15 */ + , /* OSM H16 */ + , /* OSM G16 */ + , /* OSM J15 */ + ; /* OSM K16 */ + }; + + /* OSM ETH_MDIO */ + pinctrl_mdio: eqosmdiogrp { + fsl,pins = , /* OSM T16 */ + ; /* OSM T15 */ + }; + + /* OSM ETH_B RGMII */ + pinctrl_eth_b: fecgrp { + fsl,pins = , /* OSM J1 */ + , /* OSM K1 */ + , /* OSM M1 */ + , /* OSM N1 */ + , /* OSM P1 */ + , /* OSM L1 */ + , /* OSM G1 */ + , /* OSM F1 */ + , /* OSM G2 */ + , /* OSM F2 */ + , /* OSM H1 */ + ; /* OSM J2 */ + }; + + /* OSM SPI_B_CS as GPIO */ + pinctrl_spi_b_cs0_gpio: gpio1io11grp { + fsl,pins = ; /* OSM AA23 */ + }; + + /* OSM GPIO_A_0 */ + pinctrl_gpio_a0: gpio2io0grp { + fsl,pins = ; /* OSM D17 */ + }; + + /* OSM GPIO_A_1 */ + pinctrl_gpio_a1: gpio2io1grp { + fsl,pins = ; /* OSM E17 */ + }; + + /* OSM GPIO_A_2 */ + pinctrl_gpio_a2: gpio2io2grp { + fsl,pins = ; /* OSM F17 */ + }; + + /* OSM GPIO_A_3 */ + pinctrl_gpio_a3: gpio2io3grp { + fsl,pins = ; /* OSM G17 */ + }; + + /* OSM SPI_A_CS0 as GPIO */ + pinctrl_spi_a_cs0_gpio: gpio2io12grp { + fsl,pins = ; /* OSM Y15 */ + }; + + /* OSM PWM_0 as GPIO */ + pinctrl_pwm0_gpio: gpio2io21grp { + fsl,pins = ; /* OSM E18 */ + }; + + /* OSM GPIO_A_4 */ + pinctrl_gpio_a4: gpio2io22grp { + fsl,pins = ; /* OSM H17 */ + }; + + /* OSM GPIO_A_5 */ + pinctrl_gpio_a5: gpio2io24grp { + fsl,pins = ; /* OSM J17 */ + }; + + /* On-module CTRL_INT# */ + pinctrl_ctrl_int: gpio3io27grp { + fsl,pins = ; /* CTRL_INT# */ + }; + + /* OSM GPIO_A_6 */ + pinctrl_gpio_a6: gpio4io14grp { + fsl,pins = ; /* OSM K17 */ + }; + + /* OSM GPIO_A_7 */ + pinctrl_gpio_a7: gpio4io15grp { + fsl,pins = ; /* OSM L17 */ + }; + + /* OSM I2C_B as GPIO */ + pinctrl_i2c_b_gpio: lpi2c1gpiogrp { + fsl,pins = , /* OSM AA20 */ + ; /* OSM AA21 */ + }; + + /* OSM I2C_B */ + pinctrl_i2c_b: lpi2c1grp { + fsl,pins = , /* OSM AA20 */ + ; /* OSM AA21 */ + }; + + /* On-module PMIC I2C as GPIO */ + pinctrl_pmic_i2c_gpio: lpi2c2gpiogrp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* On-module PMIC I2C */ + pinctrl_pmic_i2c: lpi2c2grp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* OSM I2C_A as GPIO */ + pinctrl_i2c_a_gpio: lpi2c3gpiogrp { + fsl,pins = , /* OSM AA16 */ + ; /* OSM AA15 */ + }; + + /* OSM I2C_A */ + pinctrl_i2c_a: lpi2c3grp { + fsl,pins = , /* OSM AA16 */ + ; /* OSM AA15 */ + }; + + /* OSM SPI_B */ + pinctrl_spi_b: lpspi1grp { + fsl,pins = , /* OSM Y22 */ + , /* OSM Y21 */ + ; /* OSM Y23 */ + }; + + /* OSM SPI_A */ + pinctrl_spi_a: lpspi8grp { + fsl,pins = , /* OSM U15 */ + , /* OSM V15 */ + ; /* OSM U16 */ + }; + + /* OSM UART_CON */ + pinctrl_uart_con: lpuart1grp { + fsl,pins = , /* OSM D22 */ + ; /* OSM D23 */ + }; + + /* OSM UART_C */ + pinctrl_uart_c: lpuart2grp { + fsl,pins = , /* OSM A22 */ + ; /* OSM B23 */ + }; + + /* OSM UART_A */ + pinctrl_uart_a: lpuart6grp { + fsl,pins = , /* OSM B13 */ + , /* OSM A14 */ + , /* OSM C14 */ + ; /* OSM C13 */ + }; + + /* OSM UART_B */ + pinctrl_uart_b: lpuart7grp { + fsl,pins = , /* OSM D13 */ + , /* OSM D14 */ + , /* OSM D16 */ + ; /* OSM D15 */ + }; + + /* OSM I2S_A */ + pinctrl_i2s_a: sai3grp { + fsl,pins = , /* OSM W20 */ + , /* OSM W21 */ + , /* OSM V21 */ + ; /* OSM W18 */ + }; + + /* OSM I2S_MCLK */ + pinctrl_i2s_a_mclk: sai3mclkgrp { + fsl,pins = ; /* OSM V18 */ + }; + + /* OSM PWM_0 */ + pinctrl_pwm0: tpm4ch1grp { + fsl,pins = ; /* OSM E18 */ + }; + + /* OSM PWM_1 */ + pinctrl_pwm1: tpm5ch2grp { + fsl,pins = ; /* OSM F18 */ + }; + + /* OSM PWM_2 */ + pinctrl_pwm2: tpm6ch1grp { + fsl,pins = ; /* OSM G18 */ + }; + + /* OSM USB_A_EN */ + pinctrl_usb_a_en: usb1engrp { + fsl,pins = ; /* OSM AC16 */ + }; + + /* OSM USB_A_OC# */ + pinctrl_usb_a_oc: usb1ocgrp { + fsl,pins = ; /* OSM AC15 */ + }; + + /* OSM USB_B_EN */ + pinctrl_usb_b_en: usb2engrp { + fsl,pins = ; /* OSM AC20 */ + }; + + /* On-module eMMC */ + pinctrl_emmc: usdhc1grp { + fsl,pins = , /* eMMC_CLK */ + , /* eMMC_CMD */ + , /* eMMC_DATA0 */ + , /* eMMC_DATA1 */ + , /* eMMC_DATA2 */ + , /* eMMC_DATA3 */ + , /* eMMC_DATA4 */ + , /* eMMC_DATA5 */ + , /* eMMC_DATA6 */ + , /* eMMC_DATA7 */ + ; /* eMMC_STROBE */ + }; + + /* OSM SDIO_A_CD# */ + pinctrl_sdio_a_cd: usdhc2cdgrp { + fsl,pins = ; /* OSM J21 */ + }; + + /* OSM SDIO_A */ + pinctrl_sdio_a: usdhc2grp { + fsl,pins = , /* OSM F21 */ + , /* OSM E20 */ + , /* OSM G20 */ + , /* OSM G21 */ + , /* OSM H20 */ + ; /* OSM H21 */ + }; + + /* OSM SDIO_A_PWR_EN */ + pinctrl_sdio_a_pwr_en: usdhc2pwrgrp { + fsl,pins = ; /* OSM D21 */ + }; + + /* On-module PMIC_SD_2_VSEL */ + pinctrl_sdio_a_vsel: usdhc2vselgrp { + fsl,pins = ; /* PMIC_SD_2_VSEL */ + }; + + /* OSM SDIO_B */ + pinctrl_sdio_b: usdhc3grp { + fsl,pins = , /* OSM K20 */ + , /* OSM K21 */ + , /* OSM L20 */ + , /* OSM L21 */ + , /* OSM M21 */ + ; /* OSM N20 */ + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = ; /* PMIC_WDOG_B */ + }; +}; -- cgit v1.2.3 From 73c898143ce0f2b76d8495a5ecdef3bf84e01c43 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 24 Sep 2026 08:57:33 +0200 Subject: arm64: dts: freescale: Add Toradex OSM iMX91 Add support for the OSM iMX91 SoM and the development carrier board that can be mated with. Link: https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx91 Link: https://www.toradex.com/products/carrier-board/osm-development-board Signed-off-by: Francesco Dolcini Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/Makefile | 2 + .../boot/dts/freescale/imx91-toradex-osm-dev.dts | 22 ++ .../boot/dts/freescale/imx91-toradex-osm.dtsi | 303 +++++++++++++++++++++ 3 files changed, 327 insertions(+) create mode 100644 arch/arm64/boot/dts/freescale/imx91-toradex-osm-dev.dts create mode 100644 arch/arm64/boot/dts/freescale/imx91-toradex-osm.dtsi diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 5aaaf99057fa..a09672b49709 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -860,6 +860,8 @@ imx91-phyboard-segin-peb-av-18-dtbs += imx91-phyboard-segin.dtb imx91-phyboard-s dtb-$(CONFIG_ARCH_MXC) += imx91-9x9-qsb-can1.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-phyboard-segin-peb-av-18.dtb +dtb-$(CONFIG_ARCH_MXC) += imx91-toradex-osm-dev.dtb + dtb-$(CONFIG_ARCH_MXC) += imx91-tqma9131-mba91xxca.dtb dtb-$(CONFIG_ARCH_MXC) += imx91-tqma9131-mba93xxca.dtb diff --git a/arch/arm64/boot/dts/freescale/imx91-toradex-osm-dev.dts b/arch/arm64/boot/dts/freescale/imx91-toradex-osm-dev.dts new file mode 100644 index 000000000000..ec5e701fb275 --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx91-toradex-osm-dev.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX91 SoM on OSM Development carrier board + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx91 + * https://www.toradex.com/products/carrier-board/osm-development-board + */ + +/dts-v1/; + +#include "imx91.dtsi" +#include "imx91-toradex-osm.dtsi" +#include "imx93-imx91-toradex-osm-dev-common.dtsi" + +/ { + model = "Toradex OSM iMX91 on OSM Development Board"; + compatible = "toradex,osm-imx91-dev", + "toradex,osm-imx91", + "fsl,imx91"; +}; diff --git a/arch/arm64/boot/dts/freescale/imx91-toradex-osm.dtsi b/arch/arm64/boot/dts/freescale/imx91-toradex-osm.dtsi new file mode 100644 index 000000000000..9d990937fd8d --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx91-toradex-osm.dtsi @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright (c) Toradex + * + * Toradex OSM iMX91 SoM + * + * https://www.toradex.com/computer-on-modules/osm-arm-family/nxp-imx91 + */ + +#include "imx91-pinfunc.h" +#include "imx93-imx91-toradex-osm-common.dtsi" + +&iomuxc { + /* OSM CAN_A */ + pinctrl_can_a: can1grp { + fsl,pins = , /* OSM AB17 */ + ; /* OSM AC17 */ + }; + + /* OSM CAN_B */ + pinctrl_can_b: can2grp { + fsl,pins = , /* OSM AC19 */ + ; /* OSM AB19 */ + }; + + /* OSM CAM_MCK */ + pinctrl_cam_mck: ccmclk1grp { + fsl,pins = ; /* OSM C2 */ + }; + + /* OSM ETH_A RGMII */ + pinctrl_eth_a: eqosgrp { + fsl,pins = , /* OSM K15 */ + , /* OSM L15 */ + , /* OSM N15 */ + , /* OSM P15 */ + , /* OSM R15 */ + , /* OSM M15 */ + , /* OSM H15 */ + , /* OSM G15 */ + , /* OSM H16 */ + , /* OSM G16 */ + , /* OSM J15 */ + ; /* OSM K16 */ + }; + + /* OSM ETH_MDIO */ + pinctrl_mdio: eqosmdiogrp { + fsl,pins = , /* OSM T16 */ + ; /* OSM T15 */ + }; + + /* OSM ETH_B RGMII */ + pinctrl_eth_b: fecgrp { + fsl,pins = , /* OSM J1 */ + , /* OSM K1 */ + , /* OSM M1 */ + , /* OSM N1 */ + , /* OSM P1 */ + , /* OSM L1 */ + , /* OSM G1 */ + , /* OSM F1 */ + , /* OSM G2 */ + , /* OSM F2 */ + , /* OSM H1 */ + ; /* OSM J2 */ + }; + + /* OSM SPI_B_CS as GPIO */ + pinctrl_spi_b_cs0_gpio: gpio1io11grp { + fsl,pins = ; /* OSM AA23 */ + }; + + /* OSM GPIO_A_0 */ + pinctrl_gpio_a0: gpio2io0grp { + fsl,pins = ; /* OSM D17 */ + }; + + /* OSM GPIO_A_1 */ + pinctrl_gpio_a1: gpio2io1grp { + fsl,pins = ; /* OSM E17 */ + }; + + /* OSM GPIO_A_2 */ + pinctrl_gpio_a2: gpio2io2grp { + fsl,pins = ; /* OSM F17 */ + }; + + /* OSM GPIO_A_3 */ + pinctrl_gpio_a3: gpio2io3grp { + fsl,pins = ; /* OSM G17 */ + }; + + /* OSM SPI_A_CS0 as GPIO */ + pinctrl_spi_a_cs0_gpio: gpio2io12grp { + fsl,pins = ; /* OSM Y15 */ + }; + + /* OSM PWM_0 as GPIO */ + pinctrl_pwm0_gpio: gpio2io21grp { + fsl,pins = ; /* OSM E18 */ + }; + + /* OSM GPIO_A_4 */ + pinctrl_gpio_a4: gpio2io22grp { + fsl,pins = ; /* OSM H17 */ + }; + + /* OSM GPIO_A_5 */ + pinctrl_gpio_a5: gpio2io24grp { + fsl,pins = ; /* OSM J17 */ + }; + + /* On-module CTRL_INT# */ + pinctrl_ctrl_int: gpio3io27grp { + fsl,pins = ; /* CTRL_INT# */ + }; + + /* OSM GPIO_A_6 */ + pinctrl_gpio_a6: gpio4io14grp { + fsl,pins = ; /* OSM K17 */ + }; + + /* OSM GPIO_A_7 */ + pinctrl_gpio_a7: gpio4io15grp { + fsl,pins = ; /* OSM L17 */ + }; + + /* OSM I2C_B as GPIO */ + pinctrl_i2c_b_gpio: lpi2c1gpiogrp { + fsl,pins = , /* OSM AA20 */ + ; /* OSM AA21 */ + }; + + /* OSM I2C_B */ + pinctrl_i2c_b: lpi2c1grp { + fsl,pins = , /* OSM AA20 */ + ; /* OSM AA21 */ + }; + + /* On-module PMIC I2C as GPIO */ + pinctrl_pmic_i2c_gpio: lpi2c2gpiogrp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* On-module PMIC I2C */ + pinctrl_pmic_i2c: lpi2c2grp { + fsl,pins = , /* PMIC_I2C_SCL */ + ; /* PMIC_I2C_SDA */ + }; + + /* OSM I2C_A as GPIO */ + pinctrl_i2c_a_gpio: lpi2c3gpiogrp { + fsl,pins = , /* OSM AA16 */ + ; /* OSM AA15 */ + }; + + /* OSM I2C_A */ + pinctrl_i2c_a: lpi2c3grp { + fsl,pins = , /* OSM AA16 */ + ; /* OSM AA15 */ + }; + + /* OSM SPI_B */ + pinctrl_spi_b: lpspi1grp { + fsl,pins = , /* OSM Y22 */ + , /* OSM Y21 */ + ; /* OSM Y23 */ + }; + + /* OSM SPI_A */ + pinctrl_spi_a: lpspi8grp { + fsl,pins = , /* OSM U15 */ + , /* OSM V15 */ + ; /* OSM U16 */ + }; + + /* OSM UART_CON */ + pinctrl_uart_con: lpuart1grp { + fsl,pins = , /* OSM D22 */ + ; /* OSM D23 */ + }; + + /* OSM UART_C */ + pinctrl_uart_c: lpuart2grp { + fsl,pins = , /* OSM A22 */ + ; /* OSM B23 */ + }; + + /* OSM UART_A */ + pinctrl_uart_a: lpuart6grp { + fsl,pins = , /* OSM B13 */ + , /* OSM A14 */ + , /* OSM C14 */ + ; /* OSM C13 */ + }; + + /* OSM UART_B */ + pinctrl_uart_b: lpuart7grp { + fsl,pins = , /* OSM D13 */ + , /* OSM D14 */ + , /* OSM D16 */ + ; /* OSM D15 */ + }; + + /* OSM I2S_A */ + pinctrl_i2s_a: sai3grp { + fsl,pins = , /* OSM W20 */ + , /* OSM W21 */ + , /* OSM V21 */ + ; /* OSM W18 */ + }; + + /* OSM I2S_MCLK */ + pinctrl_i2s_a_mclk: sai3mclkgrp { + fsl,pins = ; /* OSM V18 */ + }; + + /* OSM PWM_0 */ + pinctrl_pwm0: tpm4ch1grp { + fsl,pins = ; /* OSM E18 */ + }; + + /* OSM PWM_1 */ + pinctrl_pwm1: tpm5ch2grp { + fsl,pins = ; /* OSM F18 */ + }; + + /* OSM PWM_2 */ + pinctrl_pwm2: tpm6ch1grp { + fsl,pins = ; /* OSM G18 */ + }; + + /* OSM USB_A_EN */ + pinctrl_usb_a_en: usb1engrp { + fsl,pins = ; /* OSM AC16 */ + }; + + /* OSM USB_A_OC# */ + pinctrl_usb_a_oc: usb1ocgrp { + fsl,pins = ; /* OSM AC15 */ + }; + + /* OSM USB_B_EN */ + pinctrl_usb_b_en: usb2engrp { + fsl,pins = ; /* OSM AC20 */ + }; + + /* On-module eMMC */ + pinctrl_emmc: usdhc1grp { + fsl,pins = , /* eMMC_CLK */ + , /* eMMC_CMD */ + , /* eMMC_DATA0 */ + , /* eMMC_DATA1 */ + , /* eMMC_DATA2 */ + , /* eMMC_DATA3 */ + , /* eMMC_DATA4 */ + , /* eMMC_DATA5 */ + , /* eMMC_DATA6 */ + , /* eMMC_DATA7 */ + ; /* eMMC_STROBE */ + }; + + /* OSM SDIO_A_CD# */ + pinctrl_sdio_a_cd: usdhc2cdgrp { + fsl,pins = ; /* OSM J21 */ + }; + + /* OSM SDIO_A */ + pinctrl_sdio_a: usdhc2grp { + fsl,pins = , /* OSM F21 */ + , /* OSM E20 */ + , /* OSM G20 */ + , /* OSM G21 */ + , /* OSM H20 */ + ; /* OSM H21 */ + }; + + /* OSM SDIO_A_PWR_EN */ + pinctrl_sdio_a_pwr_en: usdhc2pwrgrp { + fsl,pins = ; /* OSM D21 */ + }; + + /* On-module PMIC_SD_2_VSEL */ + pinctrl_sdio_a_vsel: usdhc2vselgrp { + fsl,pins = ; /* PMIC_SD_2_VSEL */ + }; + + /* OSM SDIO_B */ + pinctrl_sdio_b: usdhc3grp { + fsl,pins = , /* OSM K20 */ + , /* OSM K21 */ + , /* OSM L20 */ + , /* OSM L21 */ + , /* OSM M21 */ + ; /* OSM N20 */ + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = ; /* PMIC_WDOG_B */ + }; +}; -- cgit v1.2.3 From fbbb3324b517f7cc59d424bbb90266cc1b13943d Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 23 Sep 2026 17:13:11 -0400 Subject: arm64: dts: imx8mn-solidsense-n8-compact: drop undocumented adi,led-polarity Drop undocument property adi,led-polarity and adi,link-st-polarity. ethernet-phy@0 status is disabled and no in tree overlay file to enable it. Fixed below DTB_CHECK warnings: arch/arm64/boot/dts/freescale/imx8mn-solidsense-n8-compact.dtb: ethernet-phy@0: adi,led-polarity: b'\x00\x00\x00\x01' is not of type 'object', 'integer', 'array', 'boolean', 'null' Reviewed-by: Rob Herring (Arm) Reviewed-by: Josua Mayer Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mn-solidsense-n8-compact.dts | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mn-solidsense-n8-compact.dts b/arch/arm64/boot/dts/freescale/imx8mn-solidsense-n8-compact.dts index c8c6760524db..9b8b971c1a5c 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-solidsense-n8-compact.dts +++ b/arch/arm64/boot/dts/freescale/imx8mn-solidsense-n8-compact.dts @@ -226,8 +226,6 @@ reset-assert-us = <10>; reset-deassert-us = <5000>; reset-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; - adi,led-polarity = ; - adi,link-st-polarity = ; status = "disabled"; leds { -- cgit v1.2.3 From 6bccdc6afffa4345331d46adc880bef56537421e Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Fri, 18 Sep 2026 00:25:43 +0200 Subject: arm64: dts: imx8mm-var-dart: configure SAI3 synchronous RX mode Configure SAI3 to operate in synchronous RX mode, so that the trasmit path uses the receive bit clock and frame sync signals. Remove the TX_SYNC and TX_BCLK pinmux entries, as these signals are not used in this configuration. Co-developed-by: Francesco Ferraro Signed-off-by: Francesco Ferraro Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi index 2324063f8fd9..c7a9eb23e5e8 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi @@ -305,6 +305,7 @@ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>; assigned-clock-rates = <1536000>; fsl,sai-mclk-direction-output; + fsl,sai-synchronous-rx; status = "okay"; }; @@ -446,8 +447,6 @@ MX8MM_IOMUXC_SAI3_RXFS_SAI3_RX_SYNC 0xd6 MX8MM_IOMUXC_SAI3_RXC_SAI3_RX_BCLK 0xd6 MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6 - MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6 - MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6 MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6 MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6 >; -- cgit v1.2.3 From 395280622de0c67814d8b5f06366217b3a9f70c0 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Fri, 18 Sep 2026 00:25:44 +0200 Subject: arm64: dts: imx8mm-var-dart: add TPM support Add support for the TPM available on the Variscite DART-MX8M-MINI SOM. Co-developed-by: Nate Drude Signed-off-by: Nate Drude Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi index c7a9eb23e5e8..cb7998616a87 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi @@ -138,6 +138,16 @@ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; + st33ktpm2xi2c_som: tpm@2e { + compatible = "st,st33ktpm2xi2c", "tcg,tpm-tis-i2c"; + reg = <0x2e>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_tpm_reset>; + label = "tpm"; + /* active-low TPM reset line. */ + reset-gpios = <&gpio4 31 GPIO_ACTIVE_LOW>; + }; + pmic@4b { compatible = "rohm,bd71847"; reg = <0x4b>; @@ -452,6 +462,12 @@ >; }; + pinctrl_tpm_reset: tpm-resetgrp { + fsl,pins = < + MX8MM_IOMUXC_SAI3_TXFS_GPIO4_IO31 0x19 + >; + }; + pinctrl_uart4: uart4grp { fsl,pins = < MX8MM_IOMUXC_ECSPI2_SCLK_UART4_DCE_RX 0x140 -- cgit v1.2.3 From 8c40f32361d566c0882e9d92abab36256b268291 Mon Sep 17 00:00:00 2001 From: Stefano Radaelli Date: Fri, 18 Sep 2026 00:25:45 +0200 Subject: arm64: dts: imx8mm-var-dart: increase PHY reset deassert delay The Ethernet PHY reset signal also controls the regulators supplying VDDA2P5 and VDD1P0, so releasing reset restores the PHY's 2.5 V and 1.0 V analog supplies. The existing 100 ms reset deassertion delay is not sufficient for reliable PHY detection. The TI DP83867 requires 200 ms of stabilization after power-up before MDIO register access. Increase the reset deassertion delay to 200 ms to ensure reliable PHY detection across repeated boots. Co-developed-by: Nate Drude Signed-off-by: Nate Drude Signed-off-by: Stefano Radaelli Signed-off-by: Frank Li --- arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi index cb7998616a87..c5f0e22f549b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-var-dart.dtsi @@ -123,7 +123,7 @@ reg = <0>; reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; reset-assert-us = <10000>; - reset-deassert-us = <100000>; + reset-deassert-us = <200000>; vddio-supply = <®_phy_vddio>; }; }; -- cgit v1.2.3