From 9a5f0724eaebf56449d3d0024a2f9ca3a02ac9e9 Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Tue, 28 Oct 2025 10:46:22 +0800 Subject: [PATCH 01/38] usb: ehci-mx6: Extend support to i.MX91, i.MX93, i.MX94, and i.MX95 Since the EHCI USB driver is shared across i.MX91, i.MX93, i.MX94, and i.MX95, the condition check is updated to use IMX9. Signed-off-by: Alice Guo Reviewed-by: Marek Vasut --- drivers/usb/host/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2cf687fc4f3..427b62e934b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -210,10 +210,10 @@ config USB_EHCI_MX6 config USB_EHCI_MX7 bool "Support for i.MX7/i.MX8M/i.MX9 on-chip EHCI USB controller" - depends on ARCH_MX7 || IMX8M || IMX93 || IMX95 + depends on ARCH_MX7 || IMX8M || IMX9 select EHCI_HCD_INIT_AFTER_RESET if ARCH_MX7 - select PHY if IMX8M || IMX93 || IMX95 - select NOP_PHY if IMX8M || IMX93 || IMX95 + select PHY if IMX8M || IMX9 + select NOP_PHY if IMX8M || IMX9 default y ---help--- Enables support for the on-chip EHCI controller on i.MX7/i.MX8M/i.MX9 SoCs. From af942ae3a494ae291ad08b444b6cc87cc04f55ca Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Tue, 28 Oct 2025 10:46:23 +0800 Subject: [PATCH 02/38] arm: arch-imx9: Add USB2.0 and USB3.0 base address definitions Add USB1_BASE_ADDR and USB2_BASE_ADDR for i.MX9 platform, and define USB_BASE_ADDR as an alias to USB2_BASE_ADDR. Signed-off-by: Alice Guo --- arch/arm/include/asm/arch-imx9/imx-regs.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/include/asm/arch-imx9/imx-regs.h b/arch/arm/include/asm/arch-imx9/imx-regs.h index e641ed299c0..2d084e5227a 100644 --- a/arch/arm/include/asm/arch-imx9/imx-regs.h +++ b/arch/arm/include/asm/arch-imx9/imx-regs.h @@ -39,6 +39,11 @@ #define ANATOP_BASE_ADDR 0x44480000UL +#define USB1_BASE_ADDR 0x4c100000 +#define USB2_BASE_ADDR 0x4c200000 + +#define USB_BASE_ADDR USB2_BASE_ADDR + #define BLK_CTRL_WAKEUPMIX_BASE_ADDR 0x42420000 #define BLK_CTRL_NS_ANOMIX_BASE_ADDR 0x44210000 #define BLK_CTRL_S_ANOMIX_BASE_ADDR 0x444f0000 From 28a38ab542f564b42a826de775622b0858fc18d8 Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Tue, 28 Oct 2025 10:46:24 +0800 Subject: [PATCH 03/38] imx943_evk: Enable USB 2.0 controller host mode This patch enables the USB 2.0 controller to operate in host mode on the i.MX943 EVK board. It updates the device tree files to configure the USB 2.0 controller appropriately and modifies the defconfig to include necessary support. Signed-off-by: Alice Guo --- arch/arm/dts/imx943-evk-u-boot.dtsi | 9 +++++++++ arch/arm/dts/imx943-u-boot.dtsi | 28 ++++++++++++++++++++++++++++ configs/imx943_evk_defconfig | 3 +++ 3 files changed, 40 insertions(+) diff --git a/arch/arm/dts/imx943-evk-u-boot.dtsi b/arch/arm/dts/imx943-evk-u-boot.dtsi index 5496385dc4d..e6abe7ed2e0 100644 --- a/arch/arm/dts/imx943-evk-u-boot.dtsi +++ b/arch/arm/dts/imx943-evk-u-boot.dtsi @@ -13,6 +13,15 @@ bootph-pre-ram; }; +&usb2 { + dr_mode = "host"; + hnp-disable; + srp-disable; + adp-disable; + disable-over-current; + status = "okay"; +}; + &usdhc1 { bootph-pre-ram; }; diff --git a/arch/arm/dts/imx943-u-boot.dtsi b/arch/arm/dts/imx943-u-boot.dtsi index 9c4882f7d79..9b2c1072366 100644 --- a/arch/arm/dts/imx943-u-boot.dtsi +++ b/arch/arm/dts/imx943-u-boot.dtsi @@ -83,6 +83,13 @@ }; }; }; + + usbphynop: usbphynop { + compatible = "usb-nop-xceiv"; + clocks = <&scmi_clk IMX94_CLK_HSIO>; + clock-names = "main_clk"; + #phy-cells = <0>; + }; }; &cpu0 { @@ -192,6 +199,27 @@ &{/soc} { bootph-all; + usb2: usb@4c200000 { + compatible = "fsl,imx95-usb", "fsl,imx7d-usb", "fsl,imx27-usb"; + reg = <0x0 0x4c200000 0x0 0x200>; + interrupts = , + ; + clocks = <&scmi_clk IMX94_CLK_HSIO>, + <&scmi_clk IMX94_CLK_32K>; + clock-names = "usb_ctrl_root", "usb_wakeup"; + power-domains = <&scmi_devpd IMX94_PD_HSIO_TOP>; + phys = <&usbphynop>; + fsl,usbmisc = <&usbmisc 0>; + status = "disabled"; + }; + + usbmisc: usbmisc@4c200200 { + compatible = "fsl,imx95-usbmisc", "fsl,imx7d-usbmisc", "fsl,imx6q-usbmisc"; + reg = <0x0 0x4c200200 0x0 0x200>, + <0x0 0x4c010014 0x0 0x04>; + #index-cells = <1>; + }; + elemu1: mailbox@47530000 { compatible = "fsl,imx93-mu-s4"; reg = <0x0 0x47530000 0x0 0x10000>; diff --git a/configs/imx943_evk_defconfig b/configs/imx943_evk_defconfig index 27230ed3207..d308d29a1a5 100644 --- a/configs/imx943_evk_defconfig +++ b/configs/imx943_evk_defconfig @@ -66,6 +66,7 @@ CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_POWEROFF=y +CONFIG_CMD_USB=y CONFIG_CMD_SNTP=y CONFIG_CMD_CACHE=y CONFIG_CMD_EFIDEBUG=y @@ -112,4 +113,6 @@ CONFIG_DM_REGULATOR_GPIO=y CONFIG_DM_RTC=y CONFIG_DM_SERIAL=y CONFIG_FSL_LPUART=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y CONFIG_ULP_WATCHDOG=y From 53d98faad76f8a0afd0ea91e9d00b747c6f88d5a Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 28 Oct 2025 10:46:25 +0800 Subject: [PATCH 04/38] Add serial# for SPL SDP download After update this, uuu(>1.6) can use below command to filter out devices when multi boards connected. uuu -ms ... [sudo] uuu -lsusb can list known devices with serial# informaiton. Serial number is retrieved via get_board_serial() and passed to g_dnl_set_serialnumber(). This part is conditionally compiled for i.MX94 only now. Signed-off-by: Frank Li Signed-off-by: Alice Guo Reviewed-by: Ye Li --- arch/arm/mach-imx/spl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 518d9cb1262..57ae81c7834 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -184,6 +186,16 @@ u32 spl_boot_device(void) #ifdef CONFIG_SPL_USB_GADGET int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) { +#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG +#ifdef CONFIG_IMX94 + struct tag_serialnr serialnr; + char serial_string[0x21] = {0}; + + get_board_serial(&serialnr); + snprintf(serial_string, sizeof(serial_string), "%08x%08x", serialnr.high, serialnr.low); + g_dnl_set_serialnumber(serial_string); +#endif +#endif put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM + 0xfff, &dev->idProduct); return 0; From 30c482fe6e63920b7620e32b933664359a0f1b54 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 28 Oct 2025 10:46:26 +0800 Subject: [PATCH 05/38] usb: f_sdp: Update SDP driver to support PQC container Since PQC container has changed version to 0x2 in container header, update the header's check. Signed-off-by: Ye Li Signed-off-by: Alice Guo Acked-by: Peng Fan Reviewed-by: Jacky Bai Reviewed-by: Mattijs Korpershoek --- drivers/usb/gadget/f_sdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 647001d8dd0..f72e27028b7 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -765,7 +765,7 @@ static ulong search_container_header(ulong p, int size) for (i = 0; i < size; i += 4) { hdr = (u8 *)(p + i); - if (*(hdr + 3) == 0x87 && *hdr == 0) + if (*(hdr + 3) == 0x87 && (*hdr == 0 || *hdr == 2)) if (*(hdr + 1) != 0 || *(hdr + 2) != 0) return p + i; } From ce2ab1c8c341124f1bc30d762792affd0eefdd9f Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Tue, 28 Oct 2025 10:46:27 +0800 Subject: [PATCH 06/38] phy: imx8mq-usb: Add SPL support for i.MX8MQ, i.MX8MP, i.MX95, and i.MX94 USB3.0 PHY This patch adds SPL Kconfig option (SPL_PHY_IMX8MQ_USB) for the i.MX8MQ, i.MX8MP, i.MX95, and i.MX94 USB3.0 PHY driver, allowing the driver to be compiled and probed in SPL stage. Signed-off-by: Alice Guo --- drivers/phy/Kconfig | 14 +++++++++++--- drivers/phy/Makefile | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index d36a5f00ef8..420d7c7a44d 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -289,11 +289,19 @@ config PHY_NPCM_USB Support the USB PHY in NPCM SoCs config PHY_IMX8MQ_USB - bool "NXP i.MX8MQ/i.MX8MP/i.MX95 USB PHY Driver" + bool "NXP i.MX8MQ/i.MX8MP/i.MX95/i.MX94 USB PHY Driver" depends on PHY - depends on IMX8MQ || IMX8MP || IMX95 + depends on IMX8MQ || IMX8MP || IMX95 || IMX94 help - Support the USB3.0 PHY in NXP i.MX8MQ, i.MX8MP, and i.MX95 SoC + Support the USB3.0 PHY in NXP i.MX8MQ, i.MX8MP, i.MX95, and i.MX94 SoCs. + +config SPL_PHY_IMX8MQ_USB + bool "Enable NXP i.MX8MQ/i.MX8MP/i.MX95/i.MX94 USB3.0 PHY Driver in SPL" + depends on SPL_PHY + depends on IMX8MQ || IMX8MP || IMX95 || IMX94 + help + Enable support for the USB3.0 PHY in NXP i.MX8MQ, i.MX8MP, i.MX95, and + i.MX94 SoCs in SPL. config PHY_IMX8M_PCIE bool "NXP i.MX8MM/i.MX8MP PCIe PHY Driver" diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 98c1ef8683b..5a6df0ecfeb 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -38,7 +38,7 @@ obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o obj-$(CONFIG_PHY_EXYNOS_USBDRD) += phy-exynos-usbdrd.o obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o -obj-$(CONFIG_PHY_IMX8MQ_USB) += phy-imx8mq-usb.o +obj-$(CONFIG_$(PHASE_)PHY_IMX8MQ_USB) += phy-imx8mq-usb.o obj-$(CONFIG_PHY_IMX8M_PCIE) += phy-imx8m-pcie.o obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o obj-y += cadence/ From e940ad50970dd2a7ac883c58669f6584648725c8 Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Tue, 28 Oct 2025 10:46:28 +0800 Subject: [PATCH 07/38] imx943_evk: Add support for booting from USB SDP on USB3.0 This patch is used to enable USB Gadget in SPL to make i.MX943 evk board can use SDP on USB3.0 interface. Signed-off-by: Alice Guo --- arch/arm/dts/imx943-evk-u-boot.dtsi | 24 +++++++++++++++++ arch/arm/dts/imx943-u-boot.dtsi | 40 +++++++++++++++++++++++++++++ configs/imx943_evk_defconfig | 14 ++++++++++ 3 files changed, 78 insertions(+) diff --git a/arch/arm/dts/imx943-evk-u-boot.dtsi b/arch/arm/dts/imx943-evk-u-boot.dtsi index e6abe7ed2e0..3995176f090 100644 --- a/arch/arm/dts/imx943-evk-u-boot.dtsi +++ b/arch/arm/dts/imx943-evk-u-boot.dtsi @@ -22,6 +22,30 @@ status = "okay"; }; +&usb3 { + bootph-pre-ram; + status = "okay"; +}; + +&usb3_dwc3 { + bootph-pre-ram; + dr_mode = "otg"; + hnp-disable; + srp-disable; + adp-disable; + usb-role-switch; + role-switch-default-mode = "peripheral"; + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + status = "okay"; +}; + +&usb3_phy { + bootph-pre-ram; + orientation-switch; + status = "okay"; +}; + &usdhc1 { bootph-pre-ram; }; diff --git a/arch/arm/dts/imx943-u-boot.dtsi b/arch/arm/dts/imx943-u-boot.dtsi index 9b2c1072366..8c89b8be04b 100644 --- a/arch/arm/dts/imx943-u-boot.dtsi +++ b/arch/arm/dts/imx943-u-boot.dtsi @@ -199,6 +199,46 @@ &{/soc} { bootph-all; + usb3: usb@4c010010 { + compatible = "fsl,imx95-dwc3", "fsl,imx8mp-dwc3"; + reg = <0x0 0x4c010010 0x0 0x04>, + <0x0 0x4c1f0000 0x0 0x20>; + ranges; + interrupts = ; + #address-cells = <2>; + #size-cells = <2>; + clocks = <&scmi_clk IMX94_CLK_HSIO>, + <&scmi_clk IMX94_CLK_32K>; + clock-names = "hsio", "suspend"; + power-domains = <&scmi_devpd IMX94_PD_HSIO_TOP>; + status = "disabled"; + + usb3_dwc3: usb@4c100000 { + compatible = "snps,dwc3"; + reg = <0x0 0x4c100000 0x0 0x10000>; + interrupts = ; + clocks = <&scmi_clk IMX94_CLK_HSIO>, + <&scmi_clk IMX94_CLK_24M>, + <&scmi_clk IMX94_CLK_32K>; + clock-names = "bus_early", "ref", "suspend"; + phys = <&usb3_phy>, <&usb3_phy>; + phy-names = "usb2-phy", "usb3-phy"; + snps,gfladj-refclk-lpm-sel-quirk; + snps,parkmode-disable-ss-quirk; + }; + }; + + usb3_phy: phy@4c1f0040 { + compatible = "fsl,imx95-usb-phy", "fsl,imx8mp-usb-phy"; + reg = <0x0 0x4c1f0040 0x0 0x40>, + <0x0 0x4c1fc000 0x0 0x100>; + clocks = <&scmi_clk IMX94_CLK_HSIO>; + clock-names = "phy"; + #phy-cells = <0>; + power-domains = <&scmi_devpd IMX94_PD_HSIO_TOP>; + status = "disabled"; + }; + usb2: usb@4c200000 { compatible = "fsl,imx95-usb", "fsl,imx7d-usb", "fsl,imx27-usb"; reg = <0x0 0x4c200000 0x0 0x200>; diff --git a/configs/imx943_evk_defconfig b/configs/imx943_evk_defconfig index d308d29a1a5..e4fcf2eb576 100644 --- a/configs/imx943_evk_defconfig +++ b/configs/imx943_evk_defconfig @@ -100,6 +100,8 @@ CONFIG_IMX_RGPIO2P=y CONFIG_IMX_MU_MBOX=y CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_FSL_USDHC=y +CONFIG_SPL_PHY=y +CONFIG_SPL_PHY_IMX8MQ_USB=y CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_PINCTRL_IMX_SCMI=y @@ -114,5 +116,17 @@ CONFIG_DM_RTC=y CONFIG_DM_SERIAL=y CONFIG_FSL_LPUART=y CONFIG_USB=y +CONFIG_SPL_DM_USB_GADGET=y +CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GENERIC=y +CONFIG_SPL_USB_DWC3_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_SPL_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="FSL" +CONFIG_USB_GADGET_VENDOR_NUM=0x0525 +CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5 +CONFIG_SDP_LOADADDR=0x90400000 +CONFIG_SPL_USB_SDP_SUPPORT=y CONFIG_ULP_WATCHDOG=y From f4e9645108701c1f8e2d2b66d75af95db5387f89 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 28 Oct 2025 10:46:29 +0800 Subject: [PATCH 08/38] net: fsl_enetc: Add i.MX94 support to NETC block control driver Extend the NETC block control driver to support the i.MX94 SoC. Acked-by: Peng Fan Reviewed-by: Jacky Bai Signed-off-by: Ye Li Signed-off-by: Alice Guo --- drivers/net/Kconfig | 5 +- drivers/net/fsl_enetc_netc_blk_ctrl.c | 329 +++++++++++++++++++++++++- 2 files changed, 324 insertions(+), 10 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c9b35b5a2ff..913670ce412 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1006,8 +1006,9 @@ config FSL_ENETC config FSL_ENETC_NETC_BLK_CTRL bool "NXP ENETC NETC blocks control driver" - depends on FSL_ENETC && IMX95 - default y if IMX95 + depends on FSL_ENETC + depends on IMX95 || IMX94 + default y if IMX95 || IMX94 help This driver configures Integrated Endpoint Register Block (IERB) and Privileged Register Block (PRB) of NETC. For i.MX platforms, it also diff --git a/drivers/net/fsl_enetc_netc_blk_ctrl.c b/drivers/net/fsl_enetc_netc_blk_ctrl.c index fecd66eb15a..8577bb75632 100644 --- a/drivers/net/fsl_enetc_netc_blk_ctrl.c +++ b/drivers/net/fsl_enetc_netc_blk_ctrl.c @@ -43,6 +43,18 @@ #define PCS_PROT_SFI BIT(4) #define PCS_PROT_10G_SXGMII BIT(6) +#define IMX94_MISC_SOC_CONTROL 0x0 +#define SEL_XPCS_1 BIT(1) +#define IMX94_XPCS_PORT_0 0x0 +#define IMX94_XPCS_PORT_1 0x1 + +#define IMX94_EXT_PIN_CONTROL 0x10 +#define MAC2_MAC3_SEL BIT(1) + +#define IMX94_NETC_LINK_CFG(a) (0x4c + (a) * 4) +#define NETC_LINK_CFG_MII_PROT GENMASK(3, 0) +#define NETC_LINK_CFG_IO_VAR GENMASK(19, 16) + /* NETC privileged register block register */ #define PRB_NETCRR 0x100 #define NETCRR_SR BIT(0) @@ -55,6 +67,7 @@ /* NETC integrated endpoint register block register */ #define IERB_EMDIOFAUXR 0x344 #define IERB_T0FAUXR 0x444 +#define IERB_ETBCR(a) (0x300c + 0x100 * (a)) #define IERB_EFAUXR(a) (0x3044 + 0x100 * (a)) #define IERB_VFAUXR(a) (0x4004 + 0x40 * (a)) #define FAUXR_LDID GENMASK(3, 0) @@ -64,6 +77,26 @@ #define IMX95_ENETC1_BUS_DEVFN 0x40 #define IMX95_ENETC2_BUS_DEVFN 0x80 +#define IMX94_ENETC3_BUS_DEVFN 0x0 +#define IMX94_TIMER0_BUS_DEVFN 0x1 +#define IMX94_SWITCH_BUS_DEVFN 0x2 +#define IMX94_ENETC0_BUS_DEVFN 0x100 +#define IMX94_TIMER1_BUS_DEVFN 0x101 +#define IMX94_ENETC1_BUS_DEVFN 0x140 +#define IMX94_ENETC2_BUS_DEVFN 0x180 +#define IMX94_TIMER2_BUS_DEVFN 0x181 +#define IMX94_ENETC0_LINK 3 +#define IMX94_ENETC1_LINK 4 +#define IMX94_ENETC2_LINK 5 +#define IMX94_ENETC0_OFFSET 0 +#define IMX94_ENETC1_OFFSET 1 +#define IMX94_ENETC2_OFFSET 2 +#define IMX94_SWITCH_PORT2 2 +#define IMX94_SWITCH_CPU_PORT 3 +#define IMX94_TIMER0_ID 0 +#define IMX94_TIMER1_ID 1 +#define IMX94_TIMER2_ID 2 + /* Flags for different platforms */ #define NETC_HAS_NETCMIX BIT(0) @@ -73,6 +106,15 @@ struct netc_blk_ctrl { void __iomem *netcmix; }; +struct netc_devinfo { + int (*netcmix_init)(struct udevice *dev); + int (*ierb_init)(struct udevice *dev); + void (*xpcs_port_init)(struct netc_blk_ctrl *priv, int port); +}; + +static struct netc_blk_ctrl *netc_bc; +static struct netc_devinfo *netc_di; + static void netc_reg_write(void __iomem *base, u32 offset, u32 val) { writel(val, base + offset); @@ -183,6 +225,142 @@ static int imx95_netcmix_init(struct udevice *dev) return 0; } +static int imx94_enetc_get_link_num(ofnode np) +{ + int bus_devfn; + + bus_devfn = netc_of_pci_get_bus_devfn(np); + if (bus_devfn < 0) + return -EINVAL; + + /* Parse ENETC link number */ + switch (bus_devfn) { + case IMX94_ENETC0_BUS_DEVFN: + return IMX94_ENETC0_LINK; + case IMX94_ENETC1_BUS_DEVFN: + return IMX94_ENETC1_LINK; + case IMX94_ENETC2_BUS_DEVFN: + return IMX94_ENETC2_LINK; + default: + return -EINVAL; + } +} + +static int imx94_link_config(struct netc_blk_ctrl *priv, + ofnode np, int link_id) +{ + phy_interface_t interface; + int mii_proto; + u32 val; + + interface = ofnode_read_phy_mode(np); + if (interface == -1) + return -EINVAL; + + mii_proto = netc_get_link_mii_protocol(interface); + if (mii_proto < 0) + return -EINVAL; + + val = mii_proto & NETC_LINK_CFG_MII_PROT; + if (mii_proto == MII_PROT_SERIAL) + val = u32_replace_bits(val, IO_VAR_16FF_16G_SERDES, + NETC_LINK_CFG_IO_VAR); + + netc_reg_write(priv->netcmix, IMX94_NETC_LINK_CFG(link_id), val); + + if (link_id == IMX94_ENETC0_LINK) { + val = netc_reg_read(priv->netcmix, IMX94_EXT_PIN_CONTROL); + val |= MAC2_MAC3_SEL; + netc_reg_write(priv->netcmix, IMX94_EXT_PIN_CONTROL, val); + } + + return 0; +} + +static int imx94_enetc_link_config(struct netc_blk_ctrl *priv, + ofnode np, bool *enetc0_en) +{ + int link_id; + + link_id = imx94_enetc_get_link_num(np); + if (link_id < 0) + return -EINVAL; + + if (link_id == IMX94_ENETC0_LINK) + *enetc0_en = true; + + return imx94_link_config(priv, np, link_id); +} + +static int imx94_switch_link_config(struct netc_blk_ctrl *priv, + ofnode np, bool *swp2_en) +{ + ofnode ports, child; + int port_id, err = 0; + + ports = ofnode_find_subnode(np, "ports"); + if (!ofnode_valid(ports)) + ports = ofnode_find_subnode(np, "ethernet-ports"); + if (!ofnode_valid(ports)) + return -ENODEV; + + ofnode_for_each_subnode(child, ports) { + if (ofnode_read_u32(child, "reg", &port_id) < 0) { + err = -ENODEV; + goto end; + } + + if (port_id == IMX94_SWITCH_CPU_PORT) + continue; + + if (port_id == IMX94_SWITCH_PORT2) + *swp2_en = true; + + err = imx94_link_config(priv, child, port_id); + if (err) + goto end; + } + +end: + return err; +} + +static int imx94_netcmix_init(struct udevice *dev) +{ + struct netc_blk_ctrl *priv = dev_get_priv(dev); + ofnode child, gchild; + bool enetc0_en = false, swp2_en = false; + int err; + + dev_for_each_subnode(child, dev) { + if (!ofnode_is_enabled(child)) + continue; + + ofnode_for_each_subnode(gchild, child) { + if (!ofnode_is_enabled(gchild)) + continue; + + if (ofnode_device_is_compatible(gchild, "pci1131,e101")) { + err = imx94_enetc_link_config(priv, gchild, &enetc0_en); + if (err) + return err; + } else if (ofnode_device_is_compatible(gchild, "pci1131,eef2")) { + err = imx94_switch_link_config(priv, gchild, &swp2_en); + if (err) + return err; + } + } + } + + if (enetc0_en && swp2_en) { + dev_err(dev, "Cannot enable swp2 and enetc0 at the same time\n"); + + return -EINVAL; + } + + return 0; +} + static bool netc_ierb_is_locked(struct netc_blk_ctrl *priv) { return !!(netc_reg_read(priv->prb, PRB_NETCRR) & NETCRR_LOCK); @@ -238,9 +416,99 @@ static int imx95_ierb_init(struct udevice *dev) return 0; } +static int imx94_enetc_get_enetc_offset(ofnode np) +{ + int bus_devfn; + + bus_devfn = netc_of_pci_get_bus_devfn(np); + if (bus_devfn < 0) + return -EINVAL; + + /* Parse ENETC offset */ + switch (bus_devfn) { + case IMX94_ENETC0_BUS_DEVFN: + return IMX94_ENETC0_OFFSET; + case IMX94_ENETC1_BUS_DEVFN: + return IMX94_ENETC1_OFFSET; + case IMX94_ENETC2_BUS_DEVFN: + return IMX94_ENETC2_OFFSET; + default: + return -EINVAL; + } +} + +static int imx94_enetc_get_timer_id(ofnode np) +{ + int bus_devfn; + + bus_devfn = netc_of_pci_get_bus_devfn(np); + if (bus_devfn < 0) + return -EINVAL; + + /* Parse ENETC PTP timer ID */ + switch (bus_devfn) { + case IMX94_TIMER0_BUS_DEVFN: + return IMX94_TIMER0_ID; + case IMX94_TIMER1_BUS_DEVFN: + return IMX94_TIMER1_ID; + case IMX94_TIMER2_BUS_DEVFN: + return IMX94_TIMER2_ID; + default: + return -EINVAL; + } +} + +static int imx94_enetc_update_tid(struct netc_blk_ctrl *priv, ofnode pf_np) +{ + ofnode timer_np; + int offset, tid; + + offset = imx94_enetc_get_enetc_offset(pf_np); + if (offset < 0) { + printf("Find unknown PF node.\n"); + return offset; + } + + timer_np = ofnode_parse_phandle(pf_np, "nxp,ptp-timer", 0); + if (!ofnode_valid(timer_np)) { + /* + * If nxp,ptp-timer is not set, the first timer of the bus + * where enetc is located will be used as the default timer. + */ + tid = IMX94_TIMER1_ID; + goto update_reg; + } + + tid = imx94_enetc_get_timer_id(timer_np); + if (tid < 0) { + printf("Incorrect bus/devfn of ptp-timer.\n"); + return tid; + } + +update_reg: + netc_reg_write(priv->ierb, IERB_ETBCR(offset), tid); + + return 0; +} + +static int imx94_ierb_init(struct udevice *dev) +{ + struct netc_blk_ctrl *priv = dev_get_priv(dev); + ofnode bus_np, pf_np; + int ret = 0; + + dev_for_each_subnode(bus_np, dev) + ofnode_for_each_subnode(pf_np, bus_np) + if (ofnode_device_is_compatible(pf_np, "pci1131,e101")) + ret = imx94_enetc_update_tid(priv, pf_np); + + return ret; +} + static int netc_ierb_init(struct udevice *dev) { struct netc_blk_ctrl *priv = dev_get_priv(dev); + struct netc_devinfo *devinfo = (struct netc_devinfo *)dev_get_driver_data(dev); int err; if (netc_ierb_is_locked(priv)) { @@ -251,9 +519,11 @@ static int netc_ierb_init(struct udevice *dev) } } - err = imx95_ierb_init(dev); - if (err) - return err; + if (devinfo->ierb_init) { + err = devinfo->ierb_init(dev); + if (err) + return err; + } err = netc_lock_ierb(priv); if (err) { @@ -264,6 +534,31 @@ static int netc_ierb_init(struct udevice *dev) return 0; } +static void imx94_netc_xpcs_port_init(struct netc_blk_ctrl *priv, int port) +{ + u32 val; + + val = netc_reg_read(priv->netcmix, IMX94_MISC_SOC_CONTROL); + if (port == IMX94_XPCS_PORT_1) + val |= SEL_XPCS_1; + else + val &= ~SEL_XPCS_1; + netc_reg_write(priv->netcmix, IMX94_MISC_SOC_CONTROL, val); +} + +void netc_xpcs_port_init(int port) +{ + struct netc_blk_ctrl *priv = netc_bc; + struct netc_devinfo *devinfo; + + if (!priv) + return; + + devinfo = netc_di; + if (devinfo->xpcs_port_init) + devinfo->xpcs_port_init(priv, port); +} + static int netc_prb_check_error(struct netc_blk_ctrl *priv) { if (netc_reg_read(priv->prb, PRB_NETCSR) & NETCSR_ERROR) @@ -272,14 +567,27 @@ static int netc_prb_check_error(struct netc_blk_ctrl *priv) return 0; } +static const struct netc_devinfo imx95_devinfo = { + .netcmix_init = imx95_netcmix_init, + .ierb_init = imx95_ierb_init, +}; + +static const struct netc_devinfo imx94_devinfo = { + .netcmix_init = imx94_netcmix_init, + .ierb_init = imx94_ierb_init, + .xpcs_port_init = imx94_netc_xpcs_port_init, +}; + static const struct udevice_id netc_blk_ctrl_match[] = { - { .compatible = "nxp,imx95-netc-blk-ctrl" }, + { .compatible = "nxp,imx95-netc-blk-ctrl", .data = (ulong)&imx95_devinfo }, + { .compatible = "nxp,imx94-netc-blk-ctrl", .data = (ulong)&imx94_devinfo }, {}, }; static int netc_blk_ctrl_probe(struct udevice *dev) { struct netc_blk_ctrl *priv = dev_get_priv(dev); + struct netc_devinfo *devinfo = (struct netc_devinfo *)dev_get_driver_data(dev); struct clk *ipg_clk; fdt_addr_t regs; int err; @@ -318,10 +626,12 @@ static int netc_blk_ctrl_probe(struct udevice *dev) priv->netcmix = (void __iomem *)regs; - err = imx95_netcmix_init(dev); - if (err) { - dev_err(dev, "Initializing NETCMIX failed\n"); - return err; + if (devinfo->netcmix_init) { + err = devinfo->netcmix_init(dev); + if (err) { + dev_err(dev, "Initializing NETCMIX failed\n"); + return err; + } } err = netc_ierb_init(dev); @@ -333,6 +643,9 @@ static int netc_blk_ctrl_probe(struct udevice *dev) if (netc_prb_check_error(priv) < 0) dev_warn(dev, "The current IERB configuration is invalid\n"); + netc_bc = priv; + netc_di = devinfo; + return 0; } From b810035c83cc1899067cb3b764f50ba2b7449202 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 28 Oct 2025 10:46:30 +0800 Subject: [PATCH 09/38] net: fsl_enetc_mdio: Add support for phy-supply property Add support for the optional 'phy-supply' property in the ENETC MDIO driver. This allows the driver to enable and manage the PHY's power supply via the regulator framework when specified in device tree. Signed-off-by: Ye Li Reviewed-by: Peng Fan Signed-off-by: Alice Guo --- drivers/net/fsl_enetc_mdio.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c index c1d491f2c5a..3d76d92a62a 100644 --- a/drivers/net/fsl_enetc_mdio.c +++ b/drivers/net/fsl_enetc_mdio.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "fsl_enetc.h" @@ -135,6 +137,8 @@ static int enetc_mdio_probe(struct udevice *dev) struct pci_child_plat *pplat = dev_get_parent_plat(dev); struct enetc_mdio_priv *priv = dev_get_priv(dev); u16 cmd = PCI_COMMAND_MEMORY; + int ret; + struct udevice *supply = NULL; priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { @@ -144,6 +148,27 @@ static int enetc_mdio_probe(struct udevice *dev) priv->regs_base += ENETC_MDIO_BASE; + if (CONFIG_IS_ENABLED(DM_REGULATOR)) { + ret = device_get_supply_regulator(dev, "phy-supply", + &supply); + if (ret && ret != -ENOENT) { + printf("%s: device_get_supply_regulator failed: %d\n", + __func__, ret); + return ret; + } + + if (supply) { + regulator_set_enable(supply, false); + mdelay(100); + + ret = regulator_set_enable_if_allowed(supply, true); + if (ret) { + printf("%s: Error enabling phy supply\n", dev->name); + return ret; + } + } + } + if (pplat->vendor == PCI_VENDOR_ID_PHILIPS) /* i.MX95 */ cmd |= PCI_COMMAND_MASTER; From 80430675f4b2a4ba0e4dff2111b9673a7258112b Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Tue, 28 Oct 2025 10:46:31 +0800 Subject: [PATCH 10/38] imx943_evk: Enable ENETC1 and ENETC2 With this patch, both ENETC1 and ENETC2 are functional on the i.MX943 EVK board and can be used for networking. Signed-off-by: Alice Guo --- arch/arm/dts/imx943-evk-u-boot.dtsi | 149 +++++++++++++++++++++++++ arch/arm/dts/imx943-u-boot.dtsi | 166 ++++++++++++++++++++++++++++ configs/imx943_evk_defconfig | 13 +++ 3 files changed, 328 insertions(+) diff --git a/arch/arm/dts/imx943-evk-u-boot.dtsi b/arch/arm/dts/imx943-evk-u-boot.dtsi index 3995176f090..528b3b02a3f 100644 --- a/arch/arm/dts/imx943-evk-u-boot.dtsi +++ b/arch/arm/dts/imx943-evk-u-boot.dtsi @@ -5,10 +5,109 @@ #include "imx943-u-boot.dtsi" +&enetc1 { + clocks = <&scmi_clk IMX94_CLK_MAC4>; + clock-names = "enet_ref_clk"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth3>; + phy-handle = <ðphy5>; + phy-mode = "rgmii-id"; + status = "okay"; +}; + +&enetc2 { + clocks = <&scmi_clk IMX94_CLK_MAC5>; + clock-names = "enet_ref_clk"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eth4>; + phy-handle = <ðphy6>; + phy-mode = "rgmii-id"; + status = "okay"; +}; + +&lpi2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lpi2c3>; + status = "okay"; + + pca9548_i2c3: i2c-mux@77 { + compatible = "nxp,pca9548"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x77>; + + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + + pcal6416_i2c3_u171: gpio@21 { + compatible = "nxp,pcal6416"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + + ethphy2-on-hog { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; + output-high; + }; + + ethphy3-on-hog { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; + output-high; + }; + + ethphy4-on-hog { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + }; + + lvds-en-hog { + gpio-hog; + gpios = <9 GPIO_ACTIVE_HIGH>; + output-high; + }; + }; + }; + }; +}; + &lpuart1 { bootph-pre-ram; }; +&netc_blk_ctrl { + assigned-clocks = <&scmi_clk IMX94_CLK_MAC2>, + <&scmi_clk IMX94_CLK_MAC4>, + <&scmi_clk IMX94_CLK_MAC5>; + assigned-clock-parents = <&scmi_clk IMX94_CLK_SYSPLL1_PFD0>, + <&scmi_clk IMX94_CLK_SYSPLL1_PFD0>, + <&scmi_clk IMX94_CLK_SYSPLL1_PFD0>; + assigned-clock-rates = <250000000>, <250000000>, <250000000>; + status = "okay"; +}; + +&netc_emdio { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_emdio>; + phy-supply = <®_gpy_en>; + status = "okay"; + + ethphy5: ethernet-phy@6 { + reg = <0x6>; + realtek,clkout-disable; + }; + + ethphy6: ethernet-phy@7 { + reg = <0x7>; + realtek,clkout-disable; + }; +}; + ®_usdhc2_vmmc { bootph-pre-ram; }; @@ -58,6 +157,56 @@ status = "disabled"; }; +&scmi_iomuxc { + pinctrl_emdio: emdiogrp { + fsl,pins = < + IMX94_PAD_ETH4_MDC_GPIO1__NETC_EMDC 0x57e + IMX94_PAD_ETH4_MDIO_GPIO2__NETC_EMDIO 0x97e + >; + }; + + pinctrl_eth3: eth3grp { + fsl,pins = < + IMX94_PAD_ETH3_TXD3__NETC_PINMUX_ETH3_TXD3 0x57e + IMX94_PAD_ETH3_TXD2__NETC_PINMUX_ETH3_TXD2 0x57e + IMX94_PAD_ETH3_TXD1__NETC_PINMUX_ETH3_TXD1 0x57e + IMX94_PAD_ETH3_TXD0__NETC_PINMUX_ETH3_TXD0 0x57e + IMX94_PAD_ETH3_TX_CTL__NETC_PINMUX_ETH3_TX_CTL 0x57e + IMX94_PAD_ETH3_TX_CLK__NETC_PINMUX_ETH3_TX_CLK 0x5fe + IMX94_PAD_ETH3_RX_CTL__NETC_PINMUX_ETH3_RX_CTL 0x57e + IMX94_PAD_ETH3_RX_CLK__NETC_PINMUX_ETH3_RX_CLK 0x5fe + IMX94_PAD_ETH3_RXD0__NETC_PINMUX_ETH3_RXD0 0x57e + IMX94_PAD_ETH3_RXD1__NETC_PINMUX_ETH3_RXD1 0x57e + IMX94_PAD_ETH3_RXD2__NETC_PINMUX_ETH3_RXD2 0x57e + IMX94_PAD_ETH3_RXD3__NETC_PINMUX_ETH3_RXD3 0x57e + >; + }; + + pinctrl_eth4: eth4grp { + fsl,pins = < + IMX94_PAD_ETH4_TXD3__NETC_PINMUX_ETH4_TXD3 0x57e + IMX94_PAD_ETH4_TXD2__NETC_PINMUX_ETH4_TXD2 0x57e + IMX94_PAD_ETH4_TXD1__NETC_PINMUX_ETH4_TXD1 0x57e + IMX94_PAD_ETH4_TXD0__NETC_PINMUX_ETH4_TXD0 0x57e + IMX94_PAD_ETH4_TX_CTL__NETC_PINMUX_ETH4_TX_CTL 0x57e + IMX94_PAD_ETH4_TX_CLK__NETC_PINMUX_ETH4_TX_CLK 0x5fe + IMX94_PAD_ETH4_RX_CTL__NETC_PINMUX_ETH4_RX_CTL 0x57e + IMX94_PAD_ETH4_RX_CLK__NETC_PINMUX_ETH4_RX_CLK 0x5fe + IMX94_PAD_ETH4_RXD0__NETC_PINMUX_ETH4_RXD0 0x57e + IMX94_PAD_ETH4_RXD1__NETC_PINMUX_ETH4_RXD1 0x57e + IMX94_PAD_ETH4_RXD2__NETC_PINMUX_ETH4_RXD2 0x57e + IMX94_PAD_ETH4_RXD3__NETC_PINMUX_ETH4_RXD3 0x57e + >; + }; + + pinctrl_lpi2c3: lpi2c3grp { + fsl,pins = < + IMX94_PAD_GPIO_IO16__LPI2C3_SDA 0x40000b9e + IMX94_PAD_GPIO_IO17__LPI2C3_SCL 0x40000b9e + >; + }; +}; + &pinctrl_reg_usdhc2_vmmc { bootph-pre-ram; }; diff --git a/arch/arm/dts/imx943-u-boot.dtsi b/arch/arm/dts/imx943-u-boot.dtsi index 8c89b8be04b..2b93ba9a38b 100644 --- a/arch/arm/dts/imx943-u-boot.dtsi +++ b/arch/arm/dts/imx943-u-boot.dtsi @@ -84,6 +84,25 @@ }; }; + reg_gpy_stby: regulator-gpy-stby { + compatible = "regulator-fixed"; + regulator-name = "gpy-stby"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6416_i2c3_u171 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_gpy_en: regulator-gpy-en { + compatible = "regulator-fixed"; + regulator-name = "gpy-en"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_gpy_stby>; + gpio = <&pcal6416_i2c3_u171 6 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + usbphynop: usbphynop { compatible = "usb-nop-xceiv"; clocks = <&scmi_clk IMX94_CLK_HSIO>; @@ -260,6 +279,153 @@ #index-cells = <1>; }; + netc_blk_ctrl: system-controller@4ceb0000 { + compatible = "nxp,imx94-netc-blk-ctrl"; + reg = <0x0 0x4ceb0000 0x0 0x10000>, + <0x0 0x4cec0000 0x0 0x10000>, + <0x0 0x4c810000 0x0 0x7C>; + reg-names = "ierb", "prb", "netcmix"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + power-domains = <&scmi_devpd IMX94_PD_NETC>; + status = "disabled"; + + netc_bus0: pcie@4ca00000 { + compatible = "pci-host-ecam-generic"; + reg = <0x0 0x4ca00000 0x0 0x100000>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + linux,pci-domain = <0>; + bus-range = <0x0 0x0>; + /* Switch BAR0 - non-prefetchable memory */ + ranges = <0x02000000 0x0 0x4cc00000 0x0 0x4cc00000 0x0 0x80000 + /* ENETC 3 and Timer 0 BAR0 - non-prefetchable memory */ + 0x02000000 0x0 0x4cd40000 0x0 0x4cd40000 0x0 0x60000 + /* Switch and Timer 0 BAR2 - prefetchable memory */ + 0x42000000 0x0 0x4ce00000 0x0 0x4ce00000 0x0 0x20000 + /* ENETC 3 VF0-2 BAR0 - non-prefetchable memory */ + 0x02000000 0x0 0x4ce50000 0x0 0x4ce50000 0x0 0x30000 + /* ENETC 3 VF0-2 BAR2 - prefetchable memory */ + 0x42000000 0x0 0x4ce80000 0x0 0x4ce80000 0x0 0x30000>; + + enetc3: ethernet@0,0 { + compatible = "pci1131,e110"; + reg = <0x0 0 0 0 0>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + netc_timer0: ethernet@0,1 { + compatible = "pci1131,ee02"; + reg = <0x100 0 0 0 0>; + status = "disabled"; + }; + + netc_switch: ethernet-switch@0,2 { + compatible = "pci1131,eef2", "nxp,imx943-netc-switch"; + reg = <0x200 0 0 0 0>; + status = "disabled"; + + netc_switch_ports: ports { + #address-cells = <1>; + #size-cells = <0>; + + /* External ports */ + netc_switch_port0: port@0 { + reg = <0>; + status = "disabled"; + }; + + netc_switch_port1: port@1 { + reg = <1>; + status = "disabled"; + }; + + netc_switch_port2: port@2 { + reg = <2>; + status = "disabled"; + }; + + /* Internal port, a.k.a management port */ + netc_switch_port3: port@3 { + reg = <3>; + phy-mode = "internal"; + ethernet = <&enetc3>; + status = "disabled"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; + + netc_bus1: pcie@4cb00000 { + compatible = "pci-host-ecam-generic"; + reg = <0x0 0x4cb00000 0x0 0x100000>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + linux,pci-domain = <1>; + bus-range = <0x1 0x1>; + /* ENETC 0-2 BAR0 - non-prefetchable memory */ + ranges = <0x02000000 0x0 0x4cC80000 0x0 0x4cc80000 0x0 0xc0000 + /* Timer 1-2 and EMDIO BAR0 - non-prefetchable memory */ + 0x02000000 0x0 0x4cda0000 0x0 0x4cda0000 0x0 0x60000 + /* Timer 1-2 and EMDIO BAR2 - prefetchable memory */ + 0x42000000 0x0 0x4ce20000 0x0 0x4ce20000 0x0 0x30000>; + + enetc0: ethernet@0,0 { + compatible = "pci1131,e101"; + reg = <0x10000 0 0 0 0>; + status = "disabled"; + }; + + netc_timer1: ethernet@0,1 { + compatible = "pci1131,ee02"; + reg = <0x10100 0 0 0 0>; + status = "disabled"; + }; + + enetc1: ethernet@8,0 { + compatible = "pci1131,e101"; + reg = <0x14000 0 0 0 0>; + status = "disabled"; + }; + + enetc2: ethernet@10,0 { + compatible = "pci1131,e101"; + reg = <0x18000 0 0 0 0>; + status = "disabled"; + }; + + netc_timer2: ethernet@10,1 { + compatible = "pci1131,ee02"; + reg = <0x18100 0 0 0 0>; + status = "disabled"; + }; + + netc_emdio: mdio@18,0 { + compatible = "pci1131,ee00"; + reg = <0x1c000 0 0 0 0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + }; + elemu1: mailbox@47530000 { compatible = "fsl,imx93-mu-s4"; reg = <0x0 0x47530000 0x0 0x10000>; diff --git a/configs/imx943_evk_defconfig b/configs/imx943_evk_defconfig index e4fcf2eb576..39b616e266e 100644 --- a/configs/imx943_evk_defconfig +++ b/configs/imx943_evk_defconfig @@ -39,6 +39,7 @@ CONFIG_SYS_CBSIZE=2048 CONFIG_SYS_PBSIZE=2074 CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_LATE_INIT=y +CONFIG_PCI_INIT_R=y CONFIG_SPL_MAX_SIZE=0x30000 CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_LOAD_IMX_CONTAINER=y @@ -83,6 +84,8 @@ CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SYS_RX_ETH_BUFFER=8 CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_REGMAP=y @@ -97,9 +100,19 @@ CONFIG_SPL_CLK_SCMI=y CONFIG_SPL_FIRMWARE=y # CONFIG_SCMI_AGENT_SMCCC is not set CONFIG_IMX_RGPIO2P=y +CONFIG_DM_PCA953X=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_IMX_LPI2C=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y CONFIG_IMX_MU_MBOX=y CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_FSL_USDHC=y +CONFIG_PHYLIB=y +CONFIG_PHY_REALTEK=y +CONFIG_DM_MDIO=y +CONFIG_FSL_ENETC=y +CONFIG_PCIE_ECAM_GENERIC=y CONFIG_SPL_PHY=y CONFIG_SPL_PHY_IMX8MQ_USB=y CONFIG_PINCTRL=y From 6939fc995829246270fcb55b6c9c0dc77b13af42 Mon Sep 17 00:00:00 2001 From: Andrea Calabrese Date: Fri, 31 Oct 2025 08:46:09 +0100 Subject: [PATCH 11/38] bsh: update readme with instructions to build M2B readme was missing instructions to build M2B. Now added. Signed-off-by: Andrea Calabrese Reviewed-by: Tom Rini --- board/bsh/imx6ulz_smm_m2/README | 67 ---------------------- doc/board/bsh/imx6ulz_bsh_smm_m2.rst | 85 ++++++++++++++++++++++++++++ doc/board/bsh/index.rst | 1 + 3 files changed, 86 insertions(+), 67 deletions(-) delete mode 100644 board/bsh/imx6ulz_smm_m2/README create mode 100644 doc/board/bsh/imx6ulz_bsh_smm_m2.rst diff --git a/board/bsh/imx6ulz_smm_m2/README b/board/bsh/imx6ulz_smm_m2/README deleted file mode 100644 index 03d01325a97..00000000000 --- a/board/bsh/imx6ulz_smm_m2/README +++ /dev/null @@ -1,67 +0,0 @@ -How to Update U-Boot on imx6ulz_smm_m2 board --------------------------------------------- - -Required software on the host PC: - -- UUU: https://github.com/NXPmicro/mfgtools - -Build U-Boot for m2: - -$ make mrproper -$ make imx6ulz_smm_m2_defconfig -$ make - -This generates the SPL and u-boot-dtb.img binaries. - -1. Loading U-Boot via USB Serial Download Protocol - -Copy SPL and u-boot-dtb.img to the uuu folder. - -Load the U-Boot via USB: - -$ sudo uuu -v -b nand_script.lst u-boot-with-spl.imx - -where nand_script.lst contains the following: - -uuu_version 1.2.39 - -# @_flash.bin | bootloader -# @_image [_flash.bin] | image burn to nand, default is the same as bootloader - -# This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ -SDP: boot -f _flash.bin - -# This command will be run when ROM support stream mode -# i.MX8QXP, i.MX8QM -SDPS: boot -f _flash.bin - -# These commands will be run when use SPL and will be skipped if no spl -# SDPU will be deprecated. please use SDPV instead of SDPU -# { -SDPU: delay 1000 -SDPU: write -f _flash.bin -offset 0x57c00 -SDPU: jump -# } - -# These commands will be run when use SPL and will be skipped if no spl -# if (SPL support SDPV) -# { -SDPV: delay 1000 -SDPV: write -f _flash.bin -offset 0x11000 -SDPV: jump -# } - -FB: ucmd setenv fastboot_buffer ${loadaddr} -FB: download -f _image -FB: ucmd if test ! -n "$fastboot_bytes"; then setenv fastboot_bytes $filesize; else true; fi -# Burn image to nandfit partition if needed -FB: ucmd if env exists nandfit_part; then nand erase.part nandfit; nand write ${fastboot_buffer} nandfit ${fastboot_bytes}; else true; fi; -FB: ucmd nandbcb init ${fastboot_buffer} nandboot ${fastboot_bytes} -FB: Done - -Then U-Boot starts and its messages appear in the console program. - -Use the default environment variables: - -=> env default -f -a -=> saveenv diff --git a/doc/board/bsh/imx6ulz_bsh_smm_m2.rst b/doc/board/bsh/imx6ulz_bsh_smm_m2.rst new file mode 100644 index 00000000000..0f391a17ade --- /dev/null +++ b/doc/board/bsh/imx6ulz_bsh_smm_m2.rst @@ -0,0 +1,85 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +How to Update U-Boot on imx6ulz_smm_m2 and imx6ulz_smm_m2b boards +================================================================= + +Required software on the host PC: + +- UUU: https://github.com/NXPmicro/mfgtools + +Build U-Boot for m2: + +.. code-block:: bash + + $ make mrproper + $ make imx6ulz_smm_m2_defconfig + $ make + +Build U-Boot for m2b: + +.. code-block:: bash + + $ make mrproper + $ make imx6ulz_smm_m2b_defconfig + $ make + +This generates the SPL and u-boot-dtb.img binaries. + +Loading U-Boot via USB Serial Download Protocol +----------------------------------------------- + +Copy SPL and u-boot-dtb.img to the uuu folder. + +Load the U-Boot via USB: + +.. code-block:: bash + + $ sudo uuu -v -b nand_script.lst u-boot-with-spl.imx + +where nand_script.lst contains the following: + +.. code-block:: + + uuu_version 1.2.39 + + # @_flash.bin | bootloader + # @_image [_flash.bin] | image burn to nand, default is the same as bootloader + + # This command will be run when i.MX6/7 i.MX8MM, i.MX8MQ + SDP: boot -f _flash.bin + + # This command will be run when ROM support stream mode + # i.MX8QXP, i.MX8QM + SDPS: boot -f _flash.bin + + # These commands will be run when use SPL and will be skipped if no spl + # SDPU will be deprecated. please use SDPV instead of SDPU + # { + SDPU: delay 1000 + SDPU: write -f _flash.bin -offset 0x57c00 + SDPU: jump + # } + + # These commands will be run when use SPL and will be skipped if no spl + # if (SPL support SDPV) + # { + SDPV: delay 1000 + SDPV: write -f _flash.bin -offset 0x11000 + SDPV: jump + # } + + FB: ucmd setenv fastboot_buffer ${loadaddr} + FB: download -f _image + FB: ucmd if test ! -n "$fastboot_bytes"; then setenv fastboot_bytes $filesize; else true; fi + # Burn image to nandfit partition if needed + FB: ucmd if env exists nandfit_part; then nand erase.part nandfit; nand write ${fastboot_buffer} nandfit ${fastboot_bytes}; else true; fi; + FB: ucmd nandbcb init ${fastboot_buffer} nandboot ${fastboot_bytes} + FB: Done + +Then U-Boot starts and its messages appear in the console program. + +Use the default environment variables: + +=> env default -f -a + +=> saveenv diff --git a/doc/board/bsh/index.rst b/doc/board/bsh/index.rst index 570ee4d72ed..e4f8b1f0b1c 100644 --- a/doc/board/bsh/index.rst +++ b/doc/board/bsh/index.rst @@ -7,3 +7,4 @@ BSH Hausgeraete GmbH :maxdepth: 2 imx8mn_bsh_smm_s2 + imx6ulz_bsh_smm_m2 From d5d2546647904e6c62b1e4a336ff366ec9950ca5 Mon Sep 17 00:00:00 2001 From: Andrea Calabrese Date: Fri, 31 Oct 2025 08:46:10 +0100 Subject: [PATCH 12/38] bsh: imx6ulz_smm_m2: Update imx6ulz BSH SMM M2B board Improve support for the BSH SystemMaster (SMM) M2B board. In particular, this patch adds the timing for the 512 MB version, and the spi.c reflects it by removing the safe guards. Signed-off-by: Andrea Calabrese --- board/bsh/imx6ulz_smm_m2/Makefile | 2 +- .../imx6ulz_smm_m2/ddr3l_timing_512m_m2b.c | 127 ++++++++++++++++++ board/bsh/imx6ulz_smm_m2/spl.c | 2 - 3 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m_m2b.c diff --git a/board/bsh/imx6ulz_smm_m2/Makefile b/board/bsh/imx6ulz_smm_m2/Makefile index 233bbff4c16..5ab00a5ea75 100644 --- a/board/bsh/imx6ulz_smm_m2/Makefile +++ b/board/bsh/imx6ulz_smm_m2/Makefile @@ -4,4 +4,4 @@ obj-y := imx6ulz_smm_m2.o obj-$(CONFIG_XPL_BUILD) += spl.o obj-$(CONFIG_BSH_M2_MEMORY) += ddr3l_timing_512m.o ddr3l_timing_256m.o ddr3l_timing_128m.o -obj-$(CONFIG_BSH_M2B_MEMORY) += ddr3l_timing_256m_m2b.o ddr3l_timing_128m_m2b.o +obj-$(CONFIG_BSH_M2B_MEMORY) += ddr3l_timing_512m_m2b.o ddr3l_timing_256m_m2b.o ddr3l_timing_128m_m2b.o diff --git a/board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m_m2b.c b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m_m2b.c new file mode 100644 index 00000000000..04d39a9bdd6 --- /dev/null +++ b/board/bsh/imx6ulz_smm_m2/ddr3l_timing_512m_m2b.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "spl_mtypes.h" + +static const struct dram_cfg_param ddr_ddrc_cfg_512mb[] = { + /* ============================================================================= */ + /* IOMUX */ + /* ============================================================================= */ + /* DDR IO TYPE: */ + {0x020E04B4, 0x000C0000}, /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */ + {0x020E04AC, 0x00000000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */ + + /* CLOCK: */ + {0x020E027C, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK0_P */ + + /* Control: */ + {0x020E0250, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */ + {0x020E024C, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */ + {0x020E0490, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */ + {0x020E0288, 0x000C0030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */ + {0x020E0270, 0x00000000}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 */ + /* DSE can be configured using Group Control Register: */ + /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */ + {0x020E0260, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_ODT0 */ + {0x020E0264, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_ODT1 */ + {0x020E04A0, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */ + + /* Data Strobes: */ + {0x020E0494, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */ + {0x020E0280, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0_P */ + {0x020E0284, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1_P */ + + /* Data: */ + {0x020E04B0, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */ + {0x020E0498, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_B0DS */ + {0x020E04A4, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_B1DS */ + {0x020E0244, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */ + {0x020E0248, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */ + + /* ============================================================================= */ + /* DDR Controller Registers */ + /* ============================================================================= */ + /* Manufacturer 1:NANYA */ + /* Device Part Number 1:NT5CC256M16ER-EKI */ + /* Manufacturer 2:MICRON */ + /* Device Part Number 2:MT41K256M16TW-107 */ + /* Clock Freq.: 400MHz */ + /* Density per CS in Gb: 4 */ + /* Chip Selects used:1 */ + /* Total DRAM density (Gb)4 */ + /* Number of Banks:8 */ + /* Row address: 15 */ + /* Column address: 10 */ + /* Data bus width16 */ + /* ============================================================================= */ + {0x021B001C, 0x00008000}, /* [MMDC_MDSCR] MMDC Core Special Command Register */ + + /* ====================================================== */ + /* Calibrations: */ + /* ====================================================== */ + {0x021B0800, 0xA1390003}, /* DDR_PHY_P0_MPZQHWCTRL, */ + /* enable both one-time & periodic HW ZQ calibration. */ + + {0x021B080C, 0x00060002}, + /* [MMDC_MPWLDECTRL0] MMDC PHY Write Leveling Delay Control Register 0 */ + {0x021B083C, 0x41500158}, + /* [MMDC_MPDGCTRL0] MMDC PHY Read DQS Gating Control Register 0 */ + {0x021B0848, 0x40403A3E}, + /* [MMDC_MPRDDLCTL] MMDC PHY Read delay-lines Configuration Register */ + {0x021B0850, 0x40402E28}, + /* [MMDC_MPWRDLCTL] MMDC PHY Write delay-lines Configuration Register */ + + {0x021B081C, 0x33333333}, /* [MMDC_MPRDDQBY0DL] MMDC PHY Read DQ Byte0 Delay Register */ + {0x021B0820, 0x33333333}, /* [MMDC_MPRDDQBY1DL] MMDC PHY Read DQ Byte1 Delay Register */ + + {0x021B082C, 0xf3333333}, /* [MMDC_MPWRDQBY0DL] MMDC PHY Write DQ Byte0 Delay Register */ + {0x021B0830, 0xf3333333}, /* [MMDC_MPWRDQBY1DL] MMDC PHY Write DQ Byte1 Delay Register */ + + {0x021B08C0, 0x00944009}, /* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */ + + /* Complete calibration by forced measurement: */ + {0x021B08B8, 0x00000800}, /* DDR_PHY_P0_MPMUR0, frc_msr */ + + /* ====================================================== */ + /* MMDC init: */ + /* ====================================================== */ + {0x021B0004, 0x0002002D}, /* MMDC0_MDPDC */ + {0x021B0008, 0x1B333030}, /* MMDC0_MDOTC */ + {0x021B000C, 0x616552F3}, /* MMDC0_MDCFG0 */ + {0x021B0010, 0xB62C0A63}, /* MMDC0_MDCFG1 */ + {0x021B0014, 0x01FF00DB}, /* MMDC0_MDCFG2 */ + {0x021B0018, 0x00201740}, /* MMDC0_MDMISC */ + {0x021B002C, 0x000026D2}, /* MMDC0_MDRWD; recommend to maintain the default values */ + {0x021B0030, 0x00651023}, /* MMDC0_MDOR */ + {0x021B0040, 0x0000004F}, /* CS0_END */ + {0x021B0000, 0x84180000}, /* MMDC0_MDCTL */ + + /* Mode register writes for CS0 */ + {0x021B001C, 0x02008032}, /* MMDC0_MDSCR, MR2 write, CS0 */ + {0x021B001C, 0x00008033}, /* MMDC0_MDSCR, MR3 write, CS0 */ + {0x021B001C, 0x00048031}, /* MMDC0_MDSCR, MR1 write, CS0 */ + {0x021B001C, 0x15208030}, /* MMDC0_MDSCR, MR0 write, CS0 */ + {0x021B001C, 0x04008040}, + /* MMDC0_MDSCR, ZQ calibration command sent to device on CS0 */ + + /* Mode register writes for CS, commented out automatically if only */ + /* one chip select used */ + /* {0x021B001C,0x0200803A}, */ + /* {0x021B001C,0x0000803B}, */ + /* {0x021B001C,0x00048039}, */ + /* {0x021B001C,0x15208038}, */ + /* {0x021B001C,0x04008048}, */ + + /* final DDR setup, before operation start: */ + {0x021B0020, 0x00000800}, /* MMDC0_MDREF */ + {0x021B0818, 0x00000227}, /* DDR_PHY_P0_MPODTCTRL */ + {0x021B0004, 0x0002556D}, /* MMDC0_MDPDC now SDCTL power down enabled */ + {0x021B0404, 0x00011006}, /* MMDC0_MAPSR ADOPT power down enabled */ + {0x021B001C, 0x00000000}, /* MMDC0_MDSCR, clear this register */ + /* (especially the configuration bit as initialization is complete) */ +}; + +struct dram_timing_info bsh_dram_timing_512mb = { + .ddrc_cfg = ddr_ddrc_cfg_512mb, + .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_512mb), + .dram_size = SZ_512M, +}; diff --git a/board/bsh/imx6ulz_smm_m2/spl.c b/board/bsh/imx6ulz_smm_m2/spl.c index 7aea73f0f5d..580f5ab9dff 100644 --- a/board/bsh/imx6ulz_smm_m2/spl.c +++ b/board/bsh/imx6ulz_smm_m2/spl.c @@ -53,9 +53,7 @@ static void ddr_cfg_write(const struct dram_timing_info *dram_timing_info) } static const struct dram_timing_info *board_dram_timing[] = { -#if defined(CONFIG_M2_MEMORY) &bsh_dram_timing_512mb, -#endif &bsh_dram_timing_256mb, &bsh_dram_timing_128mb, }; From 503d2088d78a25352b841e92ef6cd58693bbe3f8 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Fri, 31 Oct 2025 09:39:04 +0100 Subject: [PATCH 13/38] configs: toradex-smarc-imx95: enable USB Gadget OS Descriptors for fastboot USB OS Descriptors are used to install and configure the device without requiring any user interaction on OS which support them (e.g. Windows). Enable them in order to improve the user experience when fastboot is used. Fixes: ff0540fcfe49 ("board: toradex: add Toradex SMARC iMX95") Signed-off-by: Francesco Dolcini --- configs/toradex-smarc-imx95_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/toradex-smarc-imx95_defconfig b/configs/toradex-smarc-imx95_defconfig index 6f7b406e817..c5cea6e4e5f 100644 --- a/configs/toradex-smarc-imx95_defconfig +++ b/configs/toradex-smarc-imx95_defconfig @@ -164,6 +164,7 @@ CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Toradex" CONFIG_USB_GADGET_VENDOR_NUM=0x1b67 CONFIG_USB_GADGET_PRODUCT_NUM=0x4000 +CONFIG_USB_GADGET_OS_DESCRIPTORS=y CONFIG_CI_UDC=y CONFIG_SDP_LOADADDR=0x90400000 CONFIG_ULP_WATCHDOG=y From f78bf542fee80a2605822deac1a05c583d9284ff Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Nov 2025 12:42:39 -0300 Subject: [PATCH 14/38] imx9: scmi: Drop parenthesis around enable Signed-off-by: Marek Vasut Reviewed-by: Peng Fan --- arch/arm/mach-imx/imx9/scmi/clock_scmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/imx9/scmi/clock_scmi.c b/arch/arm/mach-imx/imx9/scmi/clock_scmi.c index fa15b5f8df9..b6be20ec674 100644 --- a/arch/arm/mach-imx/imx9/scmi/clock_scmi.c +++ b/arch/arm/mach-imx/imx9/scmi/clock_scmi.c @@ -12,7 +12,7 @@ int imx_clk_scmi_enable(u32 clock_id, bool enable) { struct scmi_clk_state_in in = { .clock_id = clock_id, - .attributes = (enable) ? 1 : 0, + .attributes = !!enable, }; struct scmi_clk_state_out out; struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, From f008af59aff947e910453227eaea0cb6724757fb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 2 Nov 2025 22:45:33 +0100 Subject: [PATCH 15/38] ARM: imx: Enable DFU SF on all i.MX6 DHSOM and include dfu_alt_info in env Enable DFU SF on all i.MX6 DHSOM so the SPI NOR can be exposed via DFU, and include dfu_alt_info which exposes the full SPI NOR via DFU. To install new bootloader into the SPI NOR using DFU, it is necessary to pad the u-boot-with-spl.imx to 0x400 Bytes offset first and then send it to the board as follows: " u-boot=> dfu 0 sf " " host$ dd if=/dev/zero of=pad.bin bs=1024 count=1 host$ cat pad.bin u-boot-with-spl.imx > flash.bin host$ dfu-util -w -a 0 -D flash.bin " Signed-off-by: Marek Vasut --- configs/dh_imx6.config | 1 + include/configs/dh_imx6.h | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/dh_imx6.config b/configs/dh_imx6.config index 01db41be2a0..b1eeb8901f4 100644 --- a/configs/dh_imx6.config +++ b/configs/dh_imx6.config @@ -60,6 +60,7 @@ CONFIG_MISC=y CONFIG_PINCTRL_IMX6=y +CONFIG_DFU_SF=y CONFIG_SDP_LOADADDR=0x17ffffc0 CONFIG_SPL_FIT=y CONFIG_SPL_SPI=y diff --git a/include/configs/dh_imx6.h b/include/configs/dh_imx6.h index 09354936d73..d849cb544be 100644 --- a/include/configs/dh_imx6.h +++ b/include/configs/dh_imx6.h @@ -38,6 +38,7 @@ #define CFG_EXTRA_ENV_SETTINGS \ "bootm_size=0x10000000\0" \ "console=ttymxc0,115200\0" \ + "dfu_alt_info=sf 0:0=flash-bin raw 0 0x200000\0" \ "fdt_addr=0x18000000\0" \ "kernel_addr_r=0x10008000\0" \ "fdt_addr_r=0x13000000\0" \ From de5ae3e43c21950b6ba03172fbed1ef42dd32db2 Mon Sep 17 00:00:00 2001 From: Alice Guo Date: Mon, 3 Nov 2025 15:36:54 +0800 Subject: [PATCH 16/38] arm64: imx8ulp: Split SRAM0 mapping to isolate the SCMI shared memory as non-cacheable This patch splits the 2MB SRAM0 mapping into three regions: - 0x22000000~0x2201f000: cacheable normal memory - 0x2201f000~0x22020000: non-cacheable device memory - 0x22020000~0x22200000: cacheable normal memory The change ensures the SCMI shared memory is non-cacheable, which avoids cache-related issues after removing mmu_set_region_dcache_behaviour() from scmi_dt_get_smt_buffer(). Signed-off-by: Alice Guo Reviewed-by: Marek Vasut --- arch/arm/mach-imx/imx8ulp/soc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c index 04c6f064130..1ee483065e8 100644 --- a/arch/arm/mach-imx/imx8ulp/soc.c +++ b/arch/arm/mach-imx/imx8ulp/soc.c @@ -384,7 +384,22 @@ static struct mm_region imx8ulp_arm64_mem_map[] = { /* SRAM0 (align with 2M) */ .virt = 0x22000000UL, .phys = 0x22000000UL, - .size = 0x200000UL, + .size = 0x1f000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* SCMI shared memory buffer must be mapped as non-cacheable. */ + .virt = 0x2201f000UL, + .phys = 0x2201f000UL, + .size = 0x1000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0x22020000UL, + .phys = 0x22020000UL, + .size = 0x1e0000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN From 69ba00627548feb501d1dc0915b41b606e1d8392 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 4 Nov 2025 02:52:03 +0100 Subject: [PATCH 17/38] arm64: dts: imx8mp: Add missing LED enumerators for DH electronics i.MX8M Plus DHCOM on PDK2 The LED enumerators are missing, which prevents the LEDs from being accurately told apart by label. Fill in the enumerators the same way they are already present on PDK3. Put this into local DT extras until matching kernel patch lands in Linux. Signed-off-by: Marek Vasut Reviewed-by: Peng Fan --- arch/arm/dts/imx8mp-dhcom-pdk2-u-boot.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/dts/imx8mp-dhcom-pdk2-u-boot.dtsi b/arch/arm/dts/imx8mp-dhcom-pdk2-u-boot.dtsi index be2d4fb184a..b8b3abd0f03 100644 --- a/arch/arm/dts/imx8mp-dhcom-pdk2-u-boot.dtsi +++ b/arch/arm/dts/imx8mp-dhcom-pdk2-u-boot.dtsi @@ -4,3 +4,23 @@ */ #include "imx8mp-dhcom-u-boot.dtsi" + +/ { + led { + led-0 { + function-enumerator = <0>; + }; + + led-1 { + function-enumerator = <1>; + }; + + led-2 { + function-enumerator = <2>; + }; + + led-3 { + function-enumerator = <3>; + }; + }; +}; From e76f9a7c9720ea3be3afe4d28fa494c8535bc505 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:50 +0800 Subject: [PATCH 18/38] remoteproc: Extend device_to_virt with a is_iomem parameter Some areas needs to be initialized by using memcpy_toio and memset_io. Following Linux Kernel commit: 40df0a91b2a5 ("remoteproc: add is_iomem to da_to_va"), add this to U-Boot. Reviewed-by: Ye Li Signed-off-by: Peng Fan --- drivers/remoteproc/renesas_apmu.c | 3 +- drivers/remoteproc/rproc-elf-loader.c | 95 ++++++++++++++++++--------- drivers/remoteproc/sandbox_testproc.c | 3 +- drivers/remoteproc/stm32_copro.c | 3 +- drivers/remoteproc/ti_k3_dsp_rproc.c | 2 +- drivers/remoteproc/ti_k3_m4_rproc.c | 2 +- drivers/remoteproc/ti_k3_r5f_rproc.c | 2 +- include/remoteproc.h | 3 +- 8 files changed, 75 insertions(+), 38 deletions(-) diff --git a/drivers/remoteproc/renesas_apmu.c b/drivers/remoteproc/renesas_apmu.c index 1a50cd3289b..91586a99e0d 100644 --- a/drivers/remoteproc/renesas_apmu.c +++ b/drivers/remoteproc/renesas_apmu.c @@ -170,11 +170,12 @@ static int renesas_apmu_rproc_init(struct udevice *dev) * @dev: corresponding remote processor device * @da: device address * @size: Size of the memory region @da is pointing to + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory * * Return: converted virtual address */ static void *renesas_apmu_rproc_device_to_virt(struct udevice *dev, ulong da, - ulong size) + ulong size, bool *is_iomem) { /* * The Cortex R52 and A76 share the same address space, diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c index 0b3941b7798..83d70c2fb54 100644 --- a/drivers/remoteproc/rproc-elf-loader.c +++ b/drivers/remoteproc/rproc-elf-loader.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause /* * Copyright (C) 2019, STMicroelectronics - All Rights Reserved + * Copyright 2025 NXP */ #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -181,27 +183,38 @@ int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size) for (i = 0; i < ehdr->e_phnum; i++, phdr++) { void *dst = (void *)(uintptr_t)phdr->p_paddr; void *src = (void *)addr + phdr->p_offset; + bool is_iomem = false; ulong dst_addr; - if (phdr->p_type != PT_LOAD) + if (phdr->p_type != PT_LOAD || !phdr->p_memsz) continue; if (ops->device_to_virt) dst = ops->device_to_virt(dev, (ulong)dst, - phdr->p_memsz); + phdr->p_memsz, &is_iomem); dev_dbg(dev, "Loading phdr %i to 0x%p (%i bytes)\n", i, dst, phdr->p_filesz); - if (phdr->p_filesz) - memcpy(dst, src, phdr->p_filesz); - if (phdr->p_filesz != phdr->p_memsz) - memset(dst + phdr->p_filesz, 0x00, - phdr->p_memsz - phdr->p_filesz); + if (phdr->p_filesz) { + if (is_iomem) + memcpy_toio(dst, src, phdr->p_filesz); + else + memcpy(dst, src, phdr->p_filesz); + } + if (phdr->p_filesz != phdr->p_memsz) { + if (is_iomem) + memset_io(dst + phdr->p_filesz, 0x00, + phdr->p_memsz - phdr->p_filesz); + else + memset(dst + phdr->p_filesz, 0x00, + phdr->p_memsz - phdr->p_filesz); + } dst_addr = map_to_sysmem(dst); - flush_cache(rounddown(dst_addr, ARCH_DMA_MINALIGN), - roundup(dst_addr + phdr->p_filesz, - ARCH_DMA_MINALIGN) - - rounddown(dst_addr, ARCH_DMA_MINALIGN)); + if (!is_iomem) { + flush_cache(rounddown(dst_addr, ARCH_DMA_MINALIGN), + roundup(dst_addr + phdr->p_filesz, ARCH_DMA_MINALIGN) - + rounddown(dst_addr, ARCH_DMA_MINALIGN)); + } } return 0; @@ -230,6 +243,7 @@ int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size) memsz = phdr->p_memsz; filesz = phdr->p_filesz; offset = phdr->p_offset; + bool is_iomem = false; if (phdr->p_type != PT_LOAD) continue; @@ -239,7 +253,7 @@ int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size) ptr = (void *)(uintptr_t)da; if (ops->device_to_virt) { - ptr = ops->device_to_virt(dev, da, phdr->p_memsz); + ptr = ops->device_to_virt(dev, da, phdr->p_memsz, &is_iomem); if (!ptr) { dev_err(dev, "bad da 0x%llx mem 0x%llx\n", da, memsz); @@ -248,14 +262,24 @@ int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size) } } - if (filesz) - memcpy(ptr, (void *)addr + offset, filesz); - if (filesz != memsz) - memset(ptr + filesz, 0x00, memsz - filesz); + if (filesz) { + if (is_iomem) + memcpy_toio(ptr, (void *)addr + offset, filesz); + else + memcpy(ptr, (void *)addr + offset, filesz); + } + if (filesz != memsz) { + if (is_iomem) + memset_io(ptr + filesz, 0x00, memsz - filesz); + else + memset(ptr + filesz, 0x00, memsz - filesz); + } - flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN), - roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) - - rounddown((ulong)ptr, ARCH_DMA_MINALIGN)); + if (!is_iomem) { + flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN), + roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) - + rounddown((ulong)ptr, ARCH_DMA_MINALIGN)); + } } return ret; @@ -381,6 +405,7 @@ int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, Elf32_Shdr *shdr; void *src, *dst; ulong dst_addr; + bool is_iomem = false; shdr = rproc_elf32_find_rsc_table(dev, fw_addr, fw_size); if (!shdr) @@ -394,18 +419,22 @@ int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr, src = (void *)fw_addr + shdr->sh_offset; if (ops->device_to_virt) - dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size); + dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size, &is_iomem); else dst = (void *)rsc_addr; dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n", (ulong)dst, *rsc_size); - memcpy(dst, src, *rsc_size); - dst_addr = map_to_sysmem(dst); - flush_cache(rounddown(dst_addr, ARCH_DMA_MINALIGN), - roundup(dst_addr + *rsc_size, ARCH_DMA_MINALIGN) - - rounddown(dst_addr, ARCH_DMA_MINALIGN)); + if (is_iomem) { + memcpy_toio(dst, src, *rsc_size); + } else { + memcpy(dst, src, *rsc_size); + dst_addr = map_to_sysmem(dst); + flush_cache(rounddown(dst_addr, ARCH_DMA_MINALIGN), + roundup(dst_addr + *rsc_size, ARCH_DMA_MINALIGN) - + rounddown(dst_addr, ARCH_DMA_MINALIGN)); + } return 0; } @@ -490,6 +519,7 @@ int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, const struct dm_rproc_ops *ops; Elf64_Shdr *shdr; void *src, *dst; + bool is_iomem = false; shdr = rproc_elf64_find_rsc_table(dev, fw_addr, fw_size); if (!shdr) @@ -503,18 +533,21 @@ int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr, src = (void *)fw_addr + shdr->sh_offset; if (ops->device_to_virt) - dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size); + dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size, &is_iomem); else dst = (void *)rsc_addr; dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n", (ulong)dst, *rsc_size); - memcpy(dst, src, *rsc_size); - flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), - roundup((unsigned long)dst + *rsc_size, - ARCH_DMA_MINALIGN) - - rounddown((unsigned long)dst, ARCH_DMA_MINALIGN)); + if (is_iomem) { + memcpy_toio(dst, src, *rsc_size); + } else { + memcpy(dst, src, *rsc_size); + flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), + roundup((unsigned long)dst + *rsc_size, ARCH_DMA_MINALIGN) - + rounddown((unsigned long)dst, ARCH_DMA_MINALIGN)); + } return 0; } diff --git a/drivers/remoteproc/sandbox_testproc.c b/drivers/remoteproc/sandbox_testproc.c index ad575a7c10f..7ed38e8656c 100644 --- a/drivers/remoteproc/sandbox_testproc.c +++ b/drivers/remoteproc/sandbox_testproc.c @@ -308,10 +308,11 @@ static int sandbox_testproc_ping(struct udevice *dev) * @dev: device to operate upon * @da: device address * @size: Size of the memory region @da is pointing to + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory * Return: converted virtual address */ static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da, - ulong size) + ulong size, bool *is_iomem) { u64 paddr; diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c index f45da9a68ac..bf721e78bb3 100644 --- a/drivers/remoteproc/stm32_copro.c +++ b/drivers/remoteproc/stm32_copro.c @@ -61,10 +61,11 @@ static int stm32_copro_probe(struct udevice *dev) * @dev: corresponding STM32 remote processor device * @da: device address * @size: Size of the memory region @da is pointing to + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory * Return: converted virtual address */ static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da, - ulong size) + ulong size, bool *is_iomem) { fdt32_t in_addr = cpu_to_be32(da), end_addr; u64 paddr; diff --git a/drivers/remoteproc/ti_k3_dsp_rproc.c b/drivers/remoteproc/ti_k3_dsp_rproc.c index 5a7d6377283..9275e1b241d 100644 --- a/drivers/remoteproc/ti_k3_dsp_rproc.c +++ b/drivers/remoteproc/ti_k3_dsp_rproc.c @@ -261,7 +261,7 @@ static int k3_dsp_reset(struct udevice *dev) return 0; } -static void *k3_dsp_da_to_va(struct udevice *dev, ulong da, ulong len) +static void *k3_dsp_da_to_va(struct udevice *dev, ulong da, ulong len, bool *is_iomem) { struct k3_dsp_privdata *dsp = dev_get_priv(dev); phys_addr_t bus_addr, dev_addr; diff --git a/drivers/remoteproc/ti_k3_m4_rproc.c b/drivers/remoteproc/ti_k3_m4_rproc.c index 31b9de71579..f358788f07f 100644 --- a/drivers/remoteproc/ti_k3_m4_rproc.c +++ b/drivers/remoteproc/ti_k3_m4_rproc.c @@ -181,7 +181,7 @@ static int k3_m4_stop(struct udevice *dev) return 0; } -static void *k3_m4_da_to_va(struct udevice *dev, ulong da, ulong len) +static void *k3_m4_da_to_va(struct udevice *dev, ulong da, ulong len, bool *is_iomem) { struct k3_m4_privdata *m4 = dev_get_priv(dev); phys_addr_t bus_addr, dev_addr; diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c index 48401bc6eb6..c738607c109 100644 --- a/drivers/remoteproc/ti_k3_r5f_rproc.c +++ b/drivers/remoteproc/ti_k3_r5f_rproc.c @@ -534,7 +534,7 @@ proc_release: return ret; } -static void *k3_r5f_da_to_va(struct udevice *dev, ulong da, ulong size) +static void *k3_r5f_da_to_va(struct udevice *dev, ulong da, ulong size, bool *is_iomem) { struct k3_r5f_core *core = dev_get_priv(dev); void __iomem *va = NULL; diff --git a/include/remoteproc.h b/include/remoteproc.h index 6f8068e1496..9adc3d17d8f 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -495,9 +495,10 @@ struct dm_rproc_ops { * @dev: Remote proc device * @da: Device address * @size: Size of the memory region @da is pointing to + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory * @return virtual address. */ - void * (*device_to_virt)(struct udevice *dev, ulong da, ulong size); + void * (*device_to_virt)(struct udevice *dev, ulong da, ulong size, bool *is_iomem); int (*add_res)(struct udevice *dev, struct rproc_mem_entry *mapping); void * (*alloc_mem)(struct udevice *dev, unsigned long len, From 640fc920e2b929cd16fe3637a32ba569ef0f6867 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:51 +0800 Subject: [PATCH 19/38] remoteproc: Add imx_rproc driver to support NXP i.MX8MP/N Support i.MX8MP/N with start/stop/device_to_virt/is_running/load implemented. The device static configuration is mostly reused from Linux Kernel with adapation to U-Boot dm_rproc_ops. The booting method: - load mmc 2:2 0x90000000 /lib/firmware/imx8mp_m7_DDR_rpmsg_lite_str_echo_ rtos.elf - rproc load 0 0x90000000 ${filesize} - rproc start 0 Reviewed-by: Ye Li Signed-off-by: Peng Fan --- MAINTAINERS | 1 + drivers/remoteproc/Kconfig | 7 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/imx_rproc.c | 233 +++++++++++++++++++++++++++++++++ drivers/remoteproc/imx_rproc.h | 56 ++++++++ 5 files changed, 298 insertions(+) create mode 100644 drivers/remoteproc/imx_rproc.c create mode 100644 drivers/remoteproc/imx_rproc.h diff --git a/MAINTAINERS b/MAINTAINERS index 8c7d0e0ab2f..818a2d74fba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -319,6 +319,7 @@ F: board/freescale/common/ F: common/spl/spl_imx_container.c F: doc/imx/ F: drivers/mailbox/imx-mailbox.c +F: drivers/remoteproc/imx* F: drivers/serial/serial_mxc.c F: include/imx_container.h diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index e9f19a69433..8056f210abc 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -33,6 +33,13 @@ config REMOTEPROC_ADI_SC5XX Say 'y' here to add support for loading code onto SHARC cores in an ADSP-SC5xx SoC from Analog Devices +config REMOTEPROC_IMX + bool "Support for NXP i.MX remoteproc" + select REMOTEPROC + depends on DM && MACH_IMX && OF_CONTROL + help + Say 'y' here to add support for i.MX remoteproc. + config REMOTEPROC_RENESAS_APMU bool "Support for Renesas R-Car Gen4 APMU start of CR52 processor" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 47bd57c7890..7ea8023c50b 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_$(PHASE_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o # Remote proc drivers - Please keep this list alphabetically sorted. obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o obj-$(CONFIG_REMOTEPROC_ADI_SC5XX) += adi_sc5xx_rproc.o +obj-$(CONFIG_REMOTEPROC_IMX) += imx_rproc.o obj-$(CONFIG_REMOTEPROC_RENESAS_APMU) += renesas_apmu.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c new file mode 100644 index 00000000000..1b2ef5005e3 --- /dev/null +++ b/drivers/remoteproc/imx_rproc.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2025 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "imx_rproc.h" + +#define IMX_RPROC_MEM_MAX 32 + +#define IMX_SIP_RPROC 0xC2000005 +#define IMX_SIP_RPROC_START 0x00 +#define IMX_SIP_RPROC_STARTED 0x01 +#define IMX_SIP_RPROC_STOP 0x02 + +struct imx_rproc { + const struct imx_rproc_dcfg *dcfg; +}; + +/* att flags: lower 16 bits specifying core, higher 16 bits for flags */ +/* M4 own area. Can be mapped at probe */ +#define ATT_OWN BIT(31) +#define ATT_IOMEM BIT(30) + +static int imx_rproc_arm_smc_start(struct udevice *dev) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res); + + return res.a0; +} + +static int imx_rproc_start(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + + if (!dcfg->ops || !dcfg->ops->start) + return -EOPNOTSUPP; + + ret = dcfg->ops->start(dev); + if (ret) + dev_err(dev, "Failed to enable remote core!\n"); + + return ret; +} + +static int imx_rproc_arm_smc_stop(struct udevice *dev) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res); + if (res.a1) + dev_info(dev, "Not in wfi, force stopped\n"); + + return res.a0; +} + +static int imx_rproc_stop(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + + if (!dcfg->ops || !dcfg->ops->stop) + return -EOPNOTSUPP; + + ret = dcfg->ops->stop(dev); + if (ret) + dev_err(dev, "Failed to stop remote core\n"); + + return ret; +} + +static int imx_rproc_arm_smc_is_running(struct udevice *dev) +{ + struct arm_smccc_res res; + + arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) + return 0; + + return 1; +} + +static int imx_rproc_is_running(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + if (!dcfg->ops || !dcfg->ops->is_running) + return 0; + + return dcfg->ops->is_running(dev); +} + +static int imx_rproc_init(struct udevice *dev) +{ + return 0; +} + +static int imx_rproc_da_to_sys(struct udevice *dev, u64 da, size_t len, u64 *sys, bool *is_iomem) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int i; + + /* parse address translation table */ + for (i = 0; i < dcfg->att_size; i++) { + const struct imx_rproc_att *att = &dcfg->att[i]; + + if (da >= att->da && da + len < att->da + att->size) { + unsigned int offset = da - att->da; + + *sys = att->sa + offset; + + if (is_iomem) + *is_iomem = att->flags & ATT_IOMEM; + + return 0; + } + } + + dev_err(dev, "Translation failed: da = 0x%llx len = 0x%zx\n", da, len); + + return -ENOENT; +} + +static void *imx_rproc_device_to_virt(struct udevice *dev, ulong da, ulong size, bool *is_iomem) +{ + u64 sys; + + if (imx_rproc_da_to_sys(dev, da, size, &sys, is_iomem)) + return NULL; + + dev_dbg(dev, "da = 0x%lx len = 0x%lx sys = 0x%llx\n", da, size, sys); + + return phys_to_virt(sys); +} + +static int imx_rproc_load(struct udevice *dev, ulong addr, ulong size) +{ + return rproc_elf_load_image(dev, addr, size); +} + +static const struct dm_rproc_ops imx_rproc_ops = { + .init = imx_rproc_init, + .start = imx_rproc_start, + .stop = imx_rproc_stop, + .load = imx_rproc_load, + .device_to_virt = imx_rproc_device_to_virt, + .is_running = imx_rproc_is_running, +}; + +static int imx_rproc_probe(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + struct imx_rproc_dcfg *dcfg = (struct imx_rproc_dcfg *)dev_get_driver_data(dev); + ofnode node; + + node = dev_ofnode(dev); + + priv->dcfg = dcfg; + + return 0; +} + +static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { + /* dev addr , sys addr , size , flags */ + /* ITCM */ + { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM }, + /* OCRAM_S */ + { 0x00180000, 0x00180000, 0x00009000, 0 }, + /* OCRAM */ + { 0x00900000, 0x00900000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00920000, 0x00920000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00940000, 0x00940000, 0x00050000, 0 }, + /* QSPI Code - alias */ + { 0x08000000, 0x08000000, 0x08000000, 0 }, + /* DDR (Code) - alias */ + { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, + /* DTCM */ + { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM }, + /* OCRAM_S - alias */ + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, + /* OCRAM */ + { 0x20200000, 0x00900000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20220000, 0x00920000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20240000, 0x00940000, 0x00040000, ATT_OWN }, + /* DDR (Data) */ + { 0x40000000, 0x40000000, 0x80000000, 0 }, +}; + +static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { + .start = imx_rproc_arm_smc_start, + .stop = imx_rproc_arm_smc_stop, + .is_running = imx_rproc_arm_smc_is_running, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { + .att = imx_rproc_att_imx8mn, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), + .method = IMX_RPROC_SMC, + .ops = &imx_rproc_ops_arm_smc, +}; + +static const struct udevice_id imx_rproc_ids[] = { + { .compatible = "fsl,imx8mn-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, + { .compatible = "fsl,imx8mp-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, + {} +}; + +U_BOOT_DRIVER(imx_rproc) = { + .name = "imx_rproc", + .of_match = imx_rproc_ids, + .id = UCLASS_REMOTEPROC, + .ops = &imx_rproc_ops, + .probe = imx_rproc_probe, + .priv_auto = sizeof(struct imx_rproc), +}; diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h new file mode 100644 index 00000000000..7a82dc4a195 --- /dev/null +++ b/drivers/remoteproc/imx_rproc.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017 Pengutronix, Oleksij Rempel + * Copyright 2021 NXP + */ + +#ifndef _IMX_RPROC_H +#define _IMX_RPROC_H + +/* address translation table */ +struct imx_rproc_att { + u32 da; /* device address (From Cortex M4 view)*/ + u32 sa; /* system bus address */ + u32 size; /* size of reg range */ + int flags; +}; + +/* Remote core start/stop method */ +enum imx_rproc_method { + IMX_RPROC_NONE, + /* Through syscon regmap */ + IMX_RPROC_MMIO, + /* Through ARM SMCCC */ + IMX_RPROC_SMC, + /* Through System Control Unit API */ + IMX_RPROC_SCU_API, + /* Through Reset Controller API */ + IMX_RPROC_RESET_CONTROLLER, + /* Through System Manager */ + IMX_RPROC_SM, +}; + +/* dcfg flags */ +#define IMX_RPROC_NEED_SYSTEM_OFF BIT(0) + +struct imx_rproc_plat_ops { + int (*start)(struct udevice *dev); + int (*stop)(struct udevice *dev); + int (*is_running)(struct udevice *dev); +}; + +struct imx_rproc_dcfg { + u32 src_reg; + u32 src_mask; + u32 src_start; + u32 src_stop; + u32 gpr_reg; + u32 gpr_wait; + const struct imx_rproc_att *att; + size_t att_size; + enum imx_rproc_method method; + u32 flags; + const struct imx_rproc_plat_ops *ops; +}; + +#endif /* _IMX_RPROC_H */ From 3c2e6002f55cbb039a59c0cf9672daec9cfacb62 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:52 +0800 Subject: [PATCH 20/38] remoteproc: imx_rproc: Support i.MX8MQ/M i.MX8MQ/M use MMIO based method to directly configure SRC registers to start/stop M4. Add mmio ops to start/stop/is_running. Add i.MX8MQ cfg data, i.MX8MN reuses i.MX8MQ data. Reviewed-by: Ye Li Signed-off-by: Peng Fan --- drivers/remoteproc/imx_rproc.c | 107 +++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 1b2ef5005e3..c71e409a00a 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -9,10 +9,27 @@ #include #include #include +#include #include +#include #include "imx_rproc.h" +#define IMX7D_SRC_SCR 0x0C +#define IMX7D_ENABLE_M4 BIT(3) +#define IMX7D_SW_M4P_RST BIT(2) +#define IMX7D_SW_M4C_RST BIT(1) +#define IMX7D_SW_M4C_NON_SCLR_RST BIT(0) + +#define IMX7D_M4_RST_MASK (IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \ + | IMX7D_SW_M4C_RST \ + | IMX7D_SW_M4C_NON_SCLR_RST) + +#define IMX7D_M4_START (IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \ + | IMX7D_SW_M4C_RST) +#define IMX7D_M4_STOP (IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST | \ + IMX7D_SW_M4C_NON_SCLR_RST) + #define IMX_RPROC_MEM_MAX 32 #define IMX_SIP_RPROC 0xC2000005 @@ -22,6 +39,7 @@ struct imx_rproc { const struct imx_rproc_dcfg *dcfg; + struct regmap *regmap; }; /* att flags: lower 16 bits specifying core, higher 16 bits for flags */ @@ -38,6 +56,14 @@ static int imx_rproc_arm_smc_start(struct udevice *dev) return res.a0; } +static int imx_rproc_mmio_start(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start); +} + static int imx_rproc_start(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); @@ -65,6 +91,14 @@ static int imx_rproc_arm_smc_stop(struct udevice *dev) return res.a0; } +static int imx_rproc_mmio_stop(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); +} + static int imx_rproc_stop(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); @@ -92,6 +126,25 @@ static int imx_rproc_arm_smc_is_running(struct udevice *dev) return 1; } +static int imx_rproc_mmio_is_running(struct udevice *dev) +{ + struct imx_rproc *priv = dev_get_priv(dev); + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + u32 val; + + ret = regmap_read(priv->regmap, dcfg->src_reg, &val); + if (ret) { + dev_err(dev, "Failed to read src\n"); + return ret; + } + + if ((val & dcfg->src_mask) != dcfg->src_stop) + return 0; + + return 1; +} + static int imx_rproc_is_running(struct udevice *dev) { struct imx_rproc *priv = dev_get_priv(dev); @@ -171,6 +224,15 @@ static int imx_rproc_probe(struct udevice *dev) priv->dcfg = dcfg; + if (dcfg->method != IMX_RPROC_MMIO) + return 0; + + priv->regmap = syscon_regmap_lookup_by_phandle(dev, "syscon"); + if (IS_ERR(priv->regmap)) { + dev_err(dev, "No syscon: %ld\n", PTR_ERR(priv->regmap)); + return PTR_ERR(priv->regmap); + } + return 0; } @@ -217,9 +279,54 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { .ops = &imx_rproc_ops_arm_smc, }; +static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { + /* dev addr , sys addr , size , flags */ + /* TCML - alias */ + { 0x00000000, 0x007e0000, 0x00020000, ATT_IOMEM}, + /* OCRAM_S */ + { 0x00180000, 0x00180000, 0x00008000, 0 }, + /* OCRAM */ + { 0x00900000, 0x00900000, 0x00020000, 0 }, + /* OCRAM */ + { 0x00920000, 0x00920000, 0x00020000, 0 }, + /* QSPI Code - alias */ + { 0x08000000, 0x08000000, 0x08000000, 0 }, + /* DDR (Code) - alias */ + { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, + /* TCML/U */ + { 0x1FFE0000, 0x007E0000, 0x00040000, ATT_OWN | ATT_IOMEM}, + /* OCRAM_S */ + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, + /* OCRAM */ + { 0x20200000, 0x00900000, 0x00020000, ATT_OWN }, + /* OCRAM */ + { 0x20220000, 0x00920000, 0x00020000, ATT_OWN }, + /* DDR (Data) */ + { 0x40000000, 0x40000000, 0x80000000, 0 }, +}; + +static const struct imx_rproc_plat_ops imx_rproc_ops_mmio = { + .start = imx_rproc_mmio_start, + .stop = imx_rproc_mmio_stop, + .is_running = imx_rproc_mmio_is_running, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { + .src_reg = IMX7D_SRC_SCR, + .src_mask = IMX7D_M4_RST_MASK, + .src_start = IMX7D_M4_START, + .src_stop = IMX7D_M4_STOP, + .att = imx_rproc_att_imx8mq, + .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), + .method = IMX_RPROC_MMIO, + .ops = &imx_rproc_ops_mmio, +}; + static const struct udevice_id imx_rproc_ids[] = { + { .compatible = "fsl,imx8mm-cm4", .data = (ulong)&imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mn-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, { .compatible = "fsl,imx8mp-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, + { .compatible = "fsl,imx8mq-cm4", .data = (ulong)&imx_rproc_cfg_imx8mq }, {} }; From f53b2c19de7b8577ead3e9e7b5ebbab052f4f7b1 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:53 +0800 Subject: [PATCH 21/38] remoteproc: imx_rproc: Add support for i.MX93 CM33 Introduce remote processor configuration for the i.MX93 Cortex-M33 core. This patch adds: - Address translation table (ATT) for i.MX93, including TCM (secure and non-secure) and DDR regions. - A new device configuration structure `imx_rproc_cfg_imx93` using SMC method and ARM SMC ops. - Device tree match entry for "fsl,imx93-cm33" This enables remoteproc framework to properly initialize and manage the Cortex-M33 core on i.MX93 platforms. Reviewed-by: Ye Li Signed-off-by: Peng Fan --- drivers/remoteproc/imx_rproc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index c71e409a00a..9bb55327998 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -322,11 +322,41 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .ops = &imx_rproc_ops_mmio, }; +static const struct imx_rproc_att imx_rproc_att_imx93[] = { + /* dev addr , sys addr , size , flags */ + /* TCM CODE NON-SECURE */ + { 0x0FFC0000, 0x201C0000, 0x00040000, ATT_OWN | ATT_IOMEM }, + + /* TCM CODE SECURE */ + { 0x1FFC0000, 0x201C0000, 0x00040000, ATT_OWN | ATT_IOMEM }, + + /* TCM SYS NON-SECURE*/ + { 0x20000000, 0x20200000, 0x00040000, ATT_OWN | ATT_IOMEM }, + + /* TCM SYS SECURE*/ + { 0x30000000, 0x20200000, 0x00040000, ATT_OWN | ATT_IOMEM }, + + /* DDR */ + { 0x80000000, 0x80000000, 0x10000000, 0 }, + { 0x90000000, 0x80000000, 0x10000000, 0 }, + + { 0xC0000000, 0xC0000000, 0x10000000, 0 }, + { 0xD0000000, 0xC0000000, 0x10000000, 0 }, +}; + +static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { + .att = imx_rproc_att_imx93, + .att_size = ARRAY_SIZE(imx_rproc_att_imx93), + .method = IMX_RPROC_SMC, + .ops = &imx_rproc_ops_arm_smc, +}; + static const struct udevice_id imx_rproc_ids[] = { { .compatible = "fsl,imx8mm-cm4", .data = (ulong)&imx_rproc_cfg_imx8mq }, { .compatible = "fsl,imx8mn-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, { .compatible = "fsl,imx8mp-cm7", .data = (ulong)&imx_rproc_cfg_imx8mn, }, { .compatible = "fsl,imx8mq-cm4", .data = (ulong)&imx_rproc_cfg_imx8mq }, + { .compatible = "fsl,imx93-cm33", .data = (ulong)&imx_rproc_cfg_imx93 }, {} }; From 6fa601053d1e478e4a95daa8c9f09c73fbc4fe23 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:54 +0800 Subject: [PATCH 22/38] arm: dts: imx8m: Add remoteproc node Add CM7/4 nodes for i.MX8MQ/M/N/P. Reviewed-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/dts/imx8mm-u-boot.dtsi | 4 ++++ arch/arm/dts/imx8mn-u-boot.dtsi | 4 ++++ arch/arm/dts/imx8mp-u-boot.dtsi | 4 ++++ arch/arm/dts/imx8mq-u-boot.dtsi | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/arch/arm/dts/imx8mm-u-boot.dtsi b/arch/arm/dts/imx8mm-u-boot.dtsi index eb5b95a1fda..d891e8062fe 100644 --- a/arch/arm/dts/imx8mm-u-boot.dtsi +++ b/arch/arm/dts/imx8mm-u-boot.dtsi @@ -15,6 +15,10 @@ }; }; #endif + imx8mm-cm4 { + compatible = "fsl,imx8mm-cm4"; + syscon = <&src>; + }; }; #ifdef CONFIG_FSL_CAAM diff --git a/arch/arm/dts/imx8mn-u-boot.dtsi b/arch/arm/dts/imx8mn-u-boot.dtsi index 4a4498b36b0..29eecd6d70d 100644 --- a/arch/arm/dts/imx8mn-u-boot.dtsi +++ b/arch/arm/dts/imx8mn-u-boot.dtsi @@ -16,6 +16,10 @@ }; #endif + imx8mn-cm7 { + compatible = "fsl,imx8mn-cm7"; + }; + wdt-reboot { compatible = "wdt-reboot"; wdt = <&wdog1>; diff --git a/arch/arm/dts/imx8mp-u-boot.dtsi b/arch/arm/dts/imx8mp-u-boot.dtsi index 9ede98a11e4..d9d220c70db 100644 --- a/arch/arm/dts/imx8mp-u-boot.dtsi +++ b/arch/arm/dts/imx8mp-u-boot.dtsi @@ -16,6 +16,10 @@ }; }; #endif + + imx8mp-cm7 { + compatible = "fsl,imx8mp-cm7"; + }; }; #ifdef CONFIG_FSL_CAAM diff --git a/arch/arm/dts/imx8mq-u-boot.dtsi b/arch/arm/dts/imx8mq-u-boot.dtsi index 93e2ef27f7c..0687fcdbd68 100644 --- a/arch/arm/dts/imx8mq-u-boot.dtsi +++ b/arch/arm/dts/imx8mq-u-boot.dtsi @@ -7,6 +7,10 @@ binman: binman { }; + imx8mq-cm4 { + compatible = "fsl,imx8mq-cm4"; + syscon = <&src>; + }; }; &soc { From 4b03912b48f0950fb127f45a0b8507741e41f987 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:55 +0800 Subject: [PATCH 23/38] imx8mp: Enable remoteproc for i.MX8MP EVK Select configs to enable remoteproc for NXP i.MX8MP EVK Reviewed-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/mach-imx/imx8m/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index f7b80f3178a..75d2772617d 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -248,6 +248,10 @@ config TARGET_IMX8MP_EVK select FSL_CAAM select ARCH_MISC_INIT select SPL_CRYPTO if SPL + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON imply OF_UPSTREAM imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND From a3b9495d803ed89dd2767101db82524c08910b5e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:56 +0800 Subject: [PATCH 24/38] imx8mm: Enable remoteproc for i.MX8MM EVK Select configs for remoteproc on i.MX8MM EVK boards Reviewed-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/mach-imx/imx8m/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 75d2772617d..35da05e93f5 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -95,6 +95,10 @@ config TARGET_IMX8MM_EVK select FSL_CAAM select ARCH_MISC_INIT select SPL_CRYPTO if SPL + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND imply OF_UPSTREAM From 59e89d07fa8ff7421b1f8d8f3ab33a82822b5c6f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:57 +0800 Subject: [PATCH 25/38] imx8mn: Enable remoteproc for i.MX8MN EVK Select configs to enable remoteproc for NXP i.MX8MN EVK boards Reviewed-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/mach-imx/imx8m/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 35da05e93f5..0584dcb580f 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -175,6 +175,10 @@ config TARGET_IMX8MN_EVK select IMX8M_LPDDR4 select FSL_CAAM select SPL_CRYPTO if SPL + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON imply OF_UPSTREAM imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND @@ -186,6 +190,10 @@ config TARGET_IMX8MN_DDR4_EVK select IMX8M_DDR4 select FSL_CAAM select SPL_CRYPTO if SPL + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON imply OF_UPSTREAM imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND From a63b3e185e7807e60e965245d46f8a49f59dd61e Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:58 +0800 Subject: [PATCH 26/38] imx8mq: Enable remoteproc for i.MX8MQ EVK Select configs to enable remoteproc for i.MX8MQ EVK Reviewed-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/mach-imx/imx8m/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 0584dcb580f..030ed2f0633 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -67,6 +67,10 @@ config TARGET_IMX8MQ_EVK select FSL_CAAM select ARCH_MISC_INIT select SPL_CRYPTO if SPL + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON imply OF_UPSTREAM imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND From 2be8a8ce18026dbb87615e739fab0d0cb7c33bb4 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:05:59 +0800 Subject: [PATCH 27/38] imx93: Enable remoteproc for i.MX93-EVK/QSB/FRDM Select configs to enable remoteproc for i.MX93-EVK/QSB/FRDM Reviewed-by: Ye Li Signed-off-by: Peng Fan --- arch/arm/mach-imx/imx9/Kconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index 6ad02b9d581..5ac51696126 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -69,6 +69,10 @@ config TARGET_IMX93_9X9_QSB imply OF_UPSTREAM imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON config TARGET_IMX93_11X11_EVK bool "imx93_11x11_evk" @@ -77,6 +81,10 @@ config TARGET_IMX93_11X11_EVK imply OF_UPSTREAM imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON config TARGET_IMX93_FRDM bool "imx93_frdm" @@ -85,6 +93,10 @@ config TARGET_IMX93_FRDM select IMX9_LPDDR4X imply BOOTSTD_FULL imply BOOTSTD_BOOTCOMMAND + select CMD_REMOTEPROC + select REMOTEPROC_IMX + select REGMAP + select SYSCON config TARGET_IMX93_VAR_SOM bool "imx93_var_som" From 1e0d22cb6b0680c4973915bfa52fa47f518c0a27 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:06:00 +0800 Subject: [PATCH 28/38] doc: board: nxp: Add remoteproc guide Add guide on how to use the Remote Processors on i.MX8M and i.MX93. Update MAINTAINERS to include doc/board/nxp. Signed-off-by: Peng Fan --- MAINTAINERS | 1 + doc/board/nxp/index.rst | 1 + doc/board/nxp/rproc.rst | 69 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 doc/board/nxp/rproc.rst diff --git a/MAINTAINERS b/MAINTAINERS index 818a2d74fba..60772a494a3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -317,6 +317,7 @@ F: arch/arm/include/asm/mach-imx/ F: board/freescale/*mx*/ F: board/freescale/common/ F: common/spl/spl_imx_container.c +F: doc/board/nxp/ F: doc/imx/ F: drivers/mailbox/imx-mailbox.c F: drivers/remoteproc/imx* diff --git a/doc/board/nxp/index.rst b/doc/board/nxp/index.rst index 670501164b5..7b881961b65 100644 --- a/doc/board/nxp/index.rst +++ b/doc/board/nxp/index.rst @@ -26,4 +26,5 @@ NXP Semiconductors mx6sabresd mx6ul_14x14_evk mx6ullevk + rproc psb diff --git a/doc/board/nxp/rproc.rst b/doc/board/nxp/rproc.rst new file mode 100644 index 00000000000..b023c1fadf6 --- /dev/null +++ b/doc/board/nxp/rproc.rst @@ -0,0 +1,69 @@ +.. SPDX-License-Identifier: GPL-2.0+ + Copyright 2025 NXP + Written by Peng Fan + +i.MX remoteproc usage guide +=========================== + +Introduction +------------ + +This guide is for giving user how to use the Remote Processors found on +various i.MX Chips. The term remote processor is indicating the Cortex-M +[4,7,33] cores inside i.MX family. + +i.MX8MM-EVK +----------- + +Steps to start the Cortex-M4 core + + load mmc 2:2 0x90000000 /lib/firmware/imx8mm_m4_TCM_rpmsg_lite_str_echo_rtos.elf + + rproc load 0 0x90000000 ${filesize} + + rproc start 0 + +i.MX8MN-EVK +----------- + +Steps to start the Cortex-M7 core + + load mmc 2:2 0x90000000 /lib/firmware/imx8mn_m7_TCM_rpmsg_lite_str_echo_rtos.elf + + rproc load 0 0x90000000 ${filesize} + + rproc start 0 + +i.MX8MQ-EVK +----------- + +Steps to start the Cortex-M4 core + + load mmc 0:2 0x90000000 /lib/firmware/imx8mq_m4_TCM_rpmsg_lite_str_echo_rtos.elf + + rproc load 0 0x90000000 ${filesize} + + rproc start 0 + +i.MX8MP-EVK +----------- + +Steps to start the Cortex-M7 core + + load mmc 2:2 0x90000000 /lib/firmware/imx8mp_m7_TCM_rpmsg_lite_str_echo_rtos.elf + + rproc load 0 0x90000000 ${filesize} + + rproc start 0 + +i.MX93-FRDM/QSB/EVK +------------------- + +Steps to start the Cortex-M33 core, need to choose the correct file for +corresponding board. + + load mmc 0:2 0x90000000 /lib/firmware/imx93-11x11-evk_m33_TCM_rpmsg_lite_str_echo_rtos.elf + + rproc load 0 0x90000000 ${filesize} + + rproc start 0 From 4faa1a5287b3a7fe6dbf7d79ec8ded86913f4f5b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 4 Nov 2025 18:06:01 +0800 Subject: [PATCH 29/38] doc: cmd: Document remoteproc usage Add documentation for rproc cmd usage. Signed-off-by: Peng Fan --- doc/usage/cmd/rproc.rst | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 doc/usage/cmd/rproc.rst diff --git a/doc/usage/cmd/rproc.rst b/doc/usage/cmd/rproc.rst new file mode 100644 index 00000000000..663c1e3d490 --- /dev/null +++ b/doc/usage/cmd/rproc.rst @@ -0,0 +1,78 @@ +.. SPDX-License-Identifier: GPL-2.0+ + Copyright 2025 NXP + Written by Peng Fan + +remoteproc command +================== + +Synopsis +-------- + +:: + + rproc init + rproc list + rproc load [addr] [size] + rproc start + rproc stop + rproc reset + rproc is_running + rproc ping + +Description +----------- + +The rproc command provides a generic U-Boot mechanism to manage the Remote +Processors inside a SoC . + +The 'rproc init' command enumerate and initialize the remote processor. + + id + remote processor id. if id is not passed, initialize all the + remote prcessors + +The 'rproc list' list available remote processors. + +The 'rproc load' load the remote processor with binary. + + id + remote processor id. + addr + address that image is loaded at. + size + image size + +The 'rproc start' start the remote processor(must be loaded). + + id + remote processor id. + +The 'rproc stop' stop the remote processor. + + id + remote processor id. + +The 'rproc reset' reset the remote processor. + + id + remote processor id. + +The 'rproc is_running' reports if the remote processor is running. + + id + remote processor id. + +The 'rproc ping' ping the remote processor for communication. + + id + remote processor id. + +Configuration +------------- + +The rproc command is only available if CONFIG_CMD_REMOTEPROC=y. + +.. toctree:: + :maxdepth: 2 + + ../../board/nxp/rproc.rst From 03584081047df5b5f24f4a0f6c1b0645036bf73e Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 4 Nov 2025 11:30:07 +0100 Subject: [PATCH 30/38] imx: kontron-sl-mx8mm: Adjust offset for U-Boot proper in case of eMMC fastboot The image offset on SD/MMC devices is 33 KiB, except for eMMC boot if fastboot is enabled. In this case it is 1 KiB. In order to make the the bootloader universal, check the fastboot OTP boot fuse and adjust the offset. Signed-off-by: Frieder Schrempf --- board/kontron/sl-mx8mm/spl.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/board/kontron/sl-mx8mm/spl.c b/board/kontron/sl-mx8mm/spl.c index e3b029752b8..50eb0eb13e1 100644 --- a/board/kontron/sl-mx8mm/spl.c +++ b/board/kontron/sl-mx8mm/spl.c @@ -186,6 +186,26 @@ static int power_init_board(void) return 0; } +unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long raw_sect) +{ + /* + * The image offset on SD/MMC devices is 33 KiB, except for eMMC boot if + * fastboot is enabled. In this case it is 1 KiB. In order to make the + * bootloader universal, check the fastboot OTP boot fuse and adjust + * the offset. + */ + if (!IS_SD(mmc) && (readl(OCOTP_BASE_ADDR + 0x470) & 0x80)) { + switch (EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config)) { + case EMMC_BOOT_PART_BOOT1: + case EMMC_BOOT_PART_BOOT2: + raw_sect -= 32 * 2; + break; + } + } + + return raw_sect; +} + void board_init_f(ulong dummy) { int ret; From 7aa1efa622dfa31c99b86997a7da97bcd553715f Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 4 Nov 2025 11:30:08 +0100 Subject: [PATCH 31/38] imx: kontron-sl-mx8mm: Implement spl_board_loader_name() This allows to print user-friendly names for the boot device probed by SPL to the console. Signed-off-by: Frieder Schrempf --- board/kontron/sl-mx8mm/spl.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/board/kontron/sl-mx8mm/spl.c b/board/kontron/sl-mx8mm/spl.c index 50eb0eb13e1..a5cdd2ab6d1 100644 --- a/board/kontron/sl-mx8mm/spl.c +++ b/board/kontron/sl-mx8mm/spl.c @@ -206,6 +206,33 @@ unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc, unsigned long return raw_sect; } +const char *spl_board_loader_name(u32 boot_device) +{ + static char name[16]; + struct mmc *mmc; + + switch (boot_device) { + case BOOT_DEVICE_SPI: + sprintf(name, "SPI NOR"); + return name; + case BOOT_DEVICE_MMC1: + mmc_init_device(0); + mmc = find_mmc_device(0); + mmc_init(mmc); + snprintf(name, sizeof(name), "eMMC %s", + emmc_hwpart_names[EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config)]); + return name; + case BOOT_DEVICE_MMC2: + sprintf(name, "SD card"); + return name; + case BOOT_DEVICE_BOARD: + sprintf(name, "USB OTG"); + return name; + } + + return NULL; +} + void board_init_f(ulong dummy) { int ret; From 0089270b45ba89188d75a680da8add2e2f62d209 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 4 Nov 2025 13:54:25 +0100 Subject: [PATCH 32/38] imx: kontron-sl-mx6ul: Enable CONFIG_BOARD_LATE_INIT to fix auto fastboot Recently code was added in board_late_init() to autostart fastboot in case of booting from USB OTG. This change was ineffective as enabling CONFIG_BOARD_LATE_INIT got lost during upstreaming. Fixes: 410d9ccc0388 ("imx: kontron-sl-mx6ul: Autostart fastboot if booted from USB") Signed-off-by: Frieder Schrempf --- configs/kontron-sl-mx6ul_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/kontron-sl-mx6ul_defconfig b/configs/kontron-sl-mx6ul_defconfig index 8e35d894dae..9f7003bf54c 100644 --- a/configs/kontron-sl-mx6ul_defconfig +++ b/configs/kontron-sl-mx6ul_defconfig @@ -34,6 +34,7 @@ CONFIG_SYS_PBSIZE=532 CONFIG_SYS_CONSOLE_IS_IN_ENV=y CONFIG_BOARD_TYPES=y CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_RAW_IMAGE_SUPPORT=y CONFIG_SPL_LEGACY_IMAGE_FORMAT=y CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK=y From f00b09abbf18b9cc91311b0330f4f49fc1917019 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 4 Nov 2025 13:54:26 +0100 Subject: [PATCH 33/38] imx: kontron: Add common function to get HW UIDs from OTPs The factory provides a CPU UID in the OTPs and the SoM module and the carrier board might provide additional UIDs in the GP registers of the OTPs. Provide a common function to load UIDs from arbitrary OTP registers and generate a serial number string that is saved in the "serial#" env variable. Signed-off-by: Frieder Schrempf --- board/kontron/common/Kconfig | 14 +++++++ board/kontron/common/Makefile | 1 + board/kontron/common/hw-uid.c | 75 +++++++++++++++++++++++++++++++++++ board/kontron/common/hw-uid.h | 26 ++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 board/kontron/common/Kconfig create mode 100644 board/kontron/common/Makefile create mode 100644 board/kontron/common/hw-uid.c create mode 100644 board/kontron/common/hw-uid.h diff --git a/board/kontron/common/Kconfig b/board/kontron/common/Kconfig new file mode 100644 index 00000000000..d581006c203 --- /dev/null +++ b/board/kontron/common/Kconfig @@ -0,0 +1,14 @@ +menuconfig KONTRON_HW_UID + bool "Enable reading Kontron HW UID from OTP fuses" + help + Enable support for reading Kontron hardware UIDs from OTP fuse registers. + The UIDs are factory-programmed for SoMs and boards and are printed to the + console and used as serial numbers if this option is enabled. + +menuconfig KONTRON_HW_UID_USE_SOC_FALLBACK + bool "Use the unique ID of the SoC as fallback serial number" + depends on KONTRON_HW_UID + default n + help + Enable the fallback to the UID of the SoC programmed by the SoC + manufacturer if no Kontron UID is found in the OTP fuses. diff --git a/board/kontron/common/Makefile b/board/kontron/common/Makefile new file mode 100644 index 00000000000..634744dc542 --- /dev/null +++ b/board/kontron/common/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KONTRON_HW_UID) += hw-uid.o diff --git a/board/kontron/common/hw-uid.c b/board/kontron/common/hw-uid.c new file mode 100644 index 00000000000..5358b1dfcf1 --- /dev/null +++ b/board/kontron/common/hw-uid.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Kontron Electronics GmbH + */ + +#include +#include +#include +#include +#include +#include + +#include "hw-uid.h" + +int get_serial_str_from_otp(struct uid_otp_loc loc, char *str, size_t str_len) +{ + u64 uid; + int ret; + + if (loc.len < 1 || loc.len > 2) { + printf("Invalid number of UID OTP registers set!\n"); + return -EINVAL; + } + + uid = readl(loc.addr); + + if (loc.len == 2) + uid |= (u64)readl(loc.addr + 0x4) << 32; + + if (!uid) + return -ENOENT; + + if (uid) { + switch (loc.format) { + case UID_OTP_FORMAT_DEC: + ret = snprintf(str, str_len, "%010llu", uid); + break; + case UID_OTP_FORMAT_HEX: + ret = snprintf(str, str_len, "%016llX", uid); + break; + } + if (ret < 0 || ret >= str_len) { + printf("Failed to convert UID!\n"); + return -EFAULT; + } + } + + return 0; +} + +void get_serial_number(struct uid_otp_loc *locs, unsigned int num) +{ + char serial_string[17]; + unsigned int i; + int ret; + + for (i = 0; i < num; i++) { + ret = get_serial_str_from_otp(locs[i], serial_string, sizeof(serial_string)); + if (ret == 0) + break; + } + + /* No valid UID in the OTP fuses, skip. */ + if (ret) { + printf("Serial Number: None\n"); + return; + } + + printf("Serial Number: %s (%s)\n", serial_string, locs[i].desc); + + if (!env_get("serial#")) + env_set("serial#", serial_string); + else if (strcmp(env_get("serial#"), serial_string)) + printf("Warning: mismatch of UIDs in env and OTPs!\n"); +} diff --git a/board/kontron/common/hw-uid.h b/board/kontron/common/hw-uid.h new file mode 100644 index 00000000000..7eaf2cc9b6c --- /dev/null +++ b/board/kontron/common/hw-uid.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2024 Kontron Electronics GmbH + */ + +#ifndef _KONTRON_HW_UID_H +#define _KONTRON_HW_UID_H + +#include +#include + +enum { + UID_OTP_FORMAT_DEC = 0, + UID_OTP_FORMAT_HEX, +}; + +struct uid_otp_loc { + u32 *addr; + size_t len; + unsigned int format; + char *desc; +}; + +void get_serial_number(struct uid_otp_loc *locs, unsigned int num); + +#endif /* _KONTRON_HW_UID_H */ From 5b4d3c81719d0e2d6ddef022c8ec904caa5a01d8 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 4 Nov 2025 13:54:27 +0100 Subject: [PATCH 34/38] imx: kontron-sl-mx6ul: Add support for reading HW UIDs The factory provides a CPU UID in the OTPs and the SoM module and the carrier board might provide additional UIDs in the GP registers of the OTPs. Load these values in the following order and create a serial number string: * Board UID (GP2) * SoM UID (GP1) * CPU UID (UNIQUE_ID) The string is stored in the "serial#" env variable and exported to Linux. Further this prints the used UID to the console which looks like this ID: 0042152331 (Board) or: ID: 0030124840 (SoM) or: ID: 4696668CD9516886 (CPU) Signed-off-by: Frieder Schrempf --- board/kontron/sl-mx6ul/Kconfig | 2 ++ board/kontron/sl-mx6ul/sl-mx6ul.c | 32 ++++++++++++++++++++++++++++++ configs/kontron-sl-mx6ul_defconfig | 1 + 3 files changed, 35 insertions(+) diff --git a/board/kontron/sl-mx6ul/Kconfig b/board/kontron/sl-mx6ul/Kconfig index 7a4ffbed289..a6d3fa49778 100644 --- a/board/kontron/sl-mx6ul/Kconfig +++ b/board/kontron/sl-mx6ul/Kconfig @@ -9,4 +9,6 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "kontron-sl-mx6ul" +source "board/kontron/common/Kconfig" + endif diff --git a/board/kontron/sl-mx6ul/sl-mx6ul.c b/board/kontron/sl-mx6ul/sl-mx6ul.c index 65f9b75c1a0..9dda8822ef9 100644 --- a/board/kontron/sl-mx6ul/sl-mx6ul.c +++ b/board/kontron/sl-mx6ul/sl-mx6ul.c @@ -14,8 +14,37 @@ #include "sl-mx6ul-common.h" +#include "../common/hw-uid.h" + DECLARE_GLOBAL_DATA_PTR; +#if IS_ENABLED(CONFIG_KONTRON_HW_UID) + +struct uid_otp_loc uid_otp_locations[] = { + { + .addr = (u32 *)(OCOTP_BASE_ADDR + 0x670), + .len = 1, + .format = UID_OTP_FORMAT_DEC, + .desc = "BOARD" + }, + { + .addr = (u32 *)(OCOTP_BASE_ADDR + 0x660), + .len = 1, + .format = UID_OTP_FORMAT_DEC, + .desc = "SOM" + }, +#if IS_ENABLED(CONFIG_KONTRON_HW_UID_USE_SOC_FALLBACK) + { + .addr = (u32 *)(OCOTP_BASE_ADDR + 0x410), + .len = 2, + .format = UID_OTP_FORMAT_HEX, + .desc = "SOC" + } +#endif +}; + +#endif /* CONFIG_KONTRON_HW_UID */ + int dram_init(void) { gd->ram_size = imx_ddr_size(); @@ -91,6 +120,9 @@ int board_init(void) int board_late_init(void) { + if (IS_ENABLED(CONFIG_KONTRON_HW_UID)) + get_serial_number(uid_otp_locations, ARRAY_SIZE(uid_otp_locations)); + if (is_boot_from_usb()) { env_set("bootdelay", "0"); env_set("bootcmd", "fastboot 0"); diff --git a/configs/kontron-sl-mx6ul_defconfig b/configs/kontron-sl-mx6ul_defconfig index 9f7003bf54c..c6d450419cc 100644 --- a/configs/kontron-sl-mx6ul_defconfig +++ b/configs/kontron-sl-mx6ul_defconfig @@ -13,6 +13,7 @@ CONFIG_ENV_SECT_SIZE=0x4000 CONFIG_MX6UL=y CONFIG_TARGET_KONTRON_MX6UL=y CONFIG_DM_GPIO=y +CONFIG_KONTRON_HW_UID=y CONFIG_DEFAULT_DEVICE_TREE="nxp/imx/imx6ul-kontron-bl" CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y From 306c3caf81a34d94a13037a6f5772b64b54fe082 Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Tue, 4 Nov 2025 13:54:28 +0100 Subject: [PATCH 35/38] imx: kontron-sl-mx8mm: Add support for reading HW UIDs The factory provides a CPU UID in the OTPs and the SoM module and the carrier board might provide additional UIDs in the GP registers of the OTPs. Load these values in the following order and create a serial number string: * Board UID (GP2) * SoM UID (GP1) * CPU UID (UNIQUE_ID) The string is stored in the "serial#" env variable and exported to Linux. Further this prints the used UID to the console which looks like this ID: 0042152331 (Board) or: ID: 0030124840 (SoM) or: ID: 4696668CD9516886 (CPU) Signed-off-by: Frieder Schrempf --- board/kontron/sl-mx8mm/Kconfig | 2 ++ board/kontron/sl-mx8mm/sl-mx8mm.c | 32 ++++++++++++++++++++++++++++++ configs/kontron-sl-mx8mm_defconfig | 1 + 3 files changed, 35 insertions(+) diff --git a/board/kontron/sl-mx8mm/Kconfig b/board/kontron/sl-mx8mm/Kconfig index 1597bcf894d..0a5123d2979 100644 --- a/board/kontron/sl-mx8mm/Kconfig +++ b/board/kontron/sl-mx8mm/Kconfig @@ -9,4 +9,6 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "kontron-sl-mx8mm" +source "board/kontron/common/Kconfig" + endif diff --git a/board/kontron/sl-mx8mm/sl-mx8mm.c b/board/kontron/sl-mx8mm/sl-mx8mm.c index df92765cb2d..d24d5286e45 100644 --- a/board/kontron/sl-mx8mm/sl-mx8mm.c +++ b/board/kontron/sl-mx8mm/sl-mx8mm.c @@ -18,8 +18,37 @@ #include #include +#include "../common/hw-uid.h" + DECLARE_GLOBAL_DATA_PTR; +#if IS_ENABLED(CONFIG_KONTRON_HW_UID) + +struct uid_otp_loc uid_otp_locations[] = { + { + .addr = (u32 *)(OCOTP_BASE_ADDR + 0x7A0), + .len = 2, + .format = UID_OTP_FORMAT_DEC, + .desc = "BOARD" + }, + { + .addr = (u32 *)(OCOTP_BASE_ADDR + 0x780), + .len = 2, + .format = UID_OTP_FORMAT_DEC, + .desc = "SOM" + }, +#if IS_ENABLED(CONFIG_KONTRON_HW_UID_USE_SOC_FALLBACK) + { + .addr = (u32 *)(OCOTP_BASE_ADDR + 0x410), + .len = 2, + .format = UID_OTP_FORMAT_HEX, + .desc = "SOC" + } +#endif +}; + +#endif /* CONFIG_KONTRON_HW_UID */ + #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) struct efi_fw_image fw_images[] = { { @@ -167,6 +196,9 @@ int board_late_init(void) env_set("touch_rst_gpio", "87"); } + if (IS_ENABLED(CONFIG_KONTRON_HW_UID)) + get_serial_number(uid_otp_locations, ARRAY_SIZE(uid_otp_locations)); + if (is_usb_boot()) { env_set("bootcmd", "fastboot 0"); env_set("bootdelay", "0"); diff --git a/configs/kontron-sl-mx8mm_defconfig b/configs/kontron-sl-mx8mm_defconfig index 42346a305f9..ed60d3b9ce4 100644 --- a/configs/kontron-sl-mx8mm_defconfig +++ b/configs/kontron-sl-mx8mm_defconfig @@ -11,6 +11,7 @@ CONFIG_ENV_OFFSET=0x1E0000 CONFIG_ENV_SECT_SIZE=0x10000 CONFIG_IMX_CONFIG="board/kontron/sl-mx8mm/imximage.cfg" CONFIG_DM_GPIO=y +CONFIG_KONTRON_HW_UID=y CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="freescale/imx8mm-kontron-bl" CONFIG_TARGET_KONTRON_MX8MM=y From 06ada9fdbfea3ee6dd76ded3723c74bd63aab801 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 4 Nov 2025 23:05:35 +0800 Subject: [PATCH 36/38] imx95_evk: Share the env file for both 19x19 EVK and 15x15 EVK Rename the env file to imx95_evk.env to share it with iMX95 15x15 EVK Signed-off-by: Ye Li --- .../freescale/imx95_evk/{imx95_19x19_evk.env => imx95_evk.env} | 0 configs/imx95_evk.config | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename board/freescale/imx95_evk/{imx95_19x19_evk.env => imx95_evk.env} (100%) diff --git a/board/freescale/imx95_evk/imx95_19x19_evk.env b/board/freescale/imx95_evk/imx95_evk.env similarity index 100% rename from board/freescale/imx95_evk/imx95_19x19_evk.env rename to board/freescale/imx95_evk/imx95_evk.env diff --git a/configs/imx95_evk.config b/configs/imx95_evk.config index 231b42cb377..631ec23c335 100644 --- a/configs/imx95_evk.config +++ b/configs/imx95_evk.config @@ -7,7 +7,7 @@ CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=3 -CONFIG_ENV_SOURCE_FILE="imx95_19x19_evk" +CONFIG_ENV_SOURCE_FILE="imx95_evk" CONFIG_SF_DEFAULT_SPEED=40000000 CONFIG_ENV_SIZE=0x4000 CONFIG_ENV_OFFSET=0x700000 From 77f67808c712d1bf0b2a34e5d0ecb49fb7865f4c Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 4 Nov 2025 23:05:36 +0800 Subject: [PATCH 37/38] arm: dts: imx95-15x15-evk: Add -u-boot.dtsi for SPL and binman Add -u-boot.dtsi for iMX95 15x15 EVK used by SPL and binman. iMX95 15x15 EVK uses LPDDR4X which needs dedicated DDR FW. Signed-off-by: Ye Li --- arch/arm/dts/imx95-15x15-evk-u-boot.dtsi | 85 ++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 arch/arm/dts/imx95-15x15-evk-u-boot.dtsi diff --git a/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi b/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi new file mode 100644 index 00000000000..514dd729be9 --- /dev/null +++ b/arch/arm/dts/imx95-15x15-evk-u-boot.dtsi @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2025 NXP + */ + +#include "imx95-u-boot.dtsi" + +/ { + aliases { + pci0 = &netc_bus0; + pci1 = &netc_bus1; + }; +}; + +&{/binman/m33-oei-ddrfw/imx-lpddr/imx-lpddr-imem} { + filename = "lpddr4x_imem_v202409.bin"; +}; + +&{/binman/m33-oei-ddrfw/imx-lpddr/imx-lpddr-dmem} { + filename = "lpddr4x_dmem_v202409.bin"; +}; + +&{/binman/m33-oei-ddrfw/imx-lpddr-qb/imx-lpddr-imem-qb} { + filename = "lpddr4x_imem_qb_v202409.bin"; +}; + +&{/binman/m33-oei-ddrfw/imx-lpddr-qb/imx-lpddr-dmem-qb} { + filename = "lpddr4x_dmem_qb_v202409.bin"; +}; + +&lpuart1 { + bootph-pre-ram; +}; + +®_usdhc2_vmmc { + bootph-pre-ram; +}; + +&usdhc1 { + bootph-pre-ram; +}; + +&usdhc2 { + bootph-pre-ram; +}; + +&wdog3 { + status = "disabled"; +}; + +&pinctrl_uart1 { + bootph-pre-ram; +}; + +&pinctrl_usdhc1 { + bootph-pre-ram; +}; + +&pinctrl_usdhc1_100mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc1_200mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc2 { + bootph-pre-ram; +}; + +&pinctrl_usdhc2_100mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc2_200mhz { + bootph-pre-ram; +}; + +&pinctrl_usdhc2_gpio { + bootph-pre-ram; +}; + +&pinctrl_reg_usdhc2_vmmc { + bootph-pre-ram; +}; From 2b7892255bd617dfc523cfe8455dbf386a3dfaf5 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 4 Nov 2025 23:05:37 +0800 Subject: [PATCH 38/38] imx95_evk: Add basic support for iMX95 15x15 EVK Add boot support and peripherals like eMMC/SD, UART, I2C, GPIO, ENETC0/1 and PCIE0/1 for iMX95 15x15 LPDDR4X EVK. Updated doc for build instructions. Signed-off-by: Ye Li --- arch/arm/mach-imx/imx9/Kconfig | 7 ++ board/freescale/imx95_evk/Kconfig | 2 +- board/freescale/imx95_evk/MAINTAINERS | 1 + configs/imx95_15x15_evk_defconfig | 148 ++++++++++++++++++++++++++ doc/board/nxp/imx95_evk.rst | 24 ++++- include/configs/imx95_evk.h | 8 +- 6 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 configs/imx95_15x15_evk_defconfig diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index 5ac51696126..d9725a96043 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -118,6 +118,13 @@ config TARGET_IMX95_19X19_EVK imply BOOTSTD_FULL imply OF_UPSTREAM +config TARGET_IMX95_15X15_EVK + bool "imx95_15x15_evk" + select IMX95 + imply BOOTSTD_BOOTCOMMAND + imply BOOTSTD_FULL + imply OF_UPSTREAM + config TARGET_IMX943_EVK bool "imx943_evk" select IMX94 diff --git a/board/freescale/imx95_evk/Kconfig b/board/freescale/imx95_evk/Kconfig index f9a67353e5d..bf746e091de 100644 --- a/board/freescale/imx95_evk/Kconfig +++ b/board/freescale/imx95_evk/Kconfig @@ -1,4 +1,4 @@ -if TARGET_IMX95_19X19_EVK +if TARGET_IMX95_19X19_EVK || TARGET_IMX95_15X15_EVK config SYS_BOARD default "imx95_evk" diff --git a/board/freescale/imx95_evk/MAINTAINERS b/board/freescale/imx95_evk/MAINTAINERS index 9d5c4e41b65..bc27786f70d 100644 --- a/board/freescale/imx95_evk/MAINTAINERS +++ b/board/freescale/imx95_evk/MAINTAINERS @@ -5,3 +5,4 @@ F: board/freescale/imx95_evk/ F: include/configs/imx95_evk.h F: configs/imx95_a0_19x19_evk_defconfig F: configs/imx95_19x19_evk_defconfig +F: configs/imx95_15x15_evk_defconfig diff --git a/configs/imx95_15x15_evk_defconfig b/configs/imx95_15x15_evk_defconfig new file mode 100644 index 00000000000..96b1d2a64af --- /dev/null +++ b/configs/imx95_15x15_evk_defconfig @@ -0,0 +1,148 @@ +CONFIG_ARM=y +CONFIG_ARCH_IMX9=y +CONFIG_TEXT_BASE=0x90200000 +CONFIG_SYS_MALLOC_LEN=0x2000000 +CONFIG_SYS_MALLOC_F_LEN=0x10000 +CONFIG_SPL_GPIO=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_NR_DRAM_BANKS=3 +CONFIG_ENV_SOURCE_FILE="imx95_evk" +CONFIG_SF_DEFAULT_SPEED=40000000 +CONFIG_ENV_SIZE=0x4000 +CONFIG_ENV_OFFSET=0x700000 +CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/scmi/imximage.cfg" +CONFIG_DM_GPIO=y +CONFIG_DEFAULT_DEVICE_TREE="freescale/imx95-15x15-evk" +CONFIG_TARGET_IMX95_15X15_EVK=y +CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_SYS_MONITOR_LEN=524288 +CONFIG_SPL_MMC=y +CONFIG_SPL_SERIAL=y +CONFIG_SPL_DRIVERS_MISC=y +CONFIG_SPL_TEXT_BASE=0x20480000 +CONFIG_SPL_HAS_BSS_LINKER_SECTION=y +CONFIG_SPL_BSS_START_ADDR=0x204d6000 +CONFIG_SPL_BSS_MAX_SIZE=0x2000 +CONFIG_SYS_LOAD_ADDR=0x90400000 +CONFIG_SPL=y +CONFIG_SPL_RECOVER_DATA_SECTION=y +CONFIG_PCI=y +CONFIG_SYS_MEMTEST_START=0x90000000 +CONFIG_SYS_MEMTEST_END=0xA0000000 +CONFIG_REMAKE_ELF=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_BOOTCOMMAND="bootflow scan -l; run bsp_bootcmd" +CONFIG_DEFAULT_FDT_FILE="imx95-15x15-evk.dtb" +CONFIG_SYS_CBSIZE=2048 +CONFIG_SYS_PBSIZE=2074 +CONFIG_BOARD_EARLY_INIT_F=y +# CONFIG_BOARD_INIT is not set +CONFIG_BOARD_LATE_INIT=y +CONFIG_PCI_INIT_R=y +CONFIG_SPL_MAX_SIZE=0x20000 +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/scmi/container.cfg" +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x93200000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x80000 +CONFIG_SPL_SYS_MMCSD_RAW_MODE=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1040 +CONFIG_SPL_I2C=y +CONFIG_SPL_DM_MAILBOX=y +CONFIG_SPL_POWER=y +CONFIG_SPL_WATCHDOG=y +CONFIG_SYS_PROMPT="u-boot=> " +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_NVEDIT_EFI=y +CONFIG_CRC32_VERIFY=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DFU=y +CONFIG_CMD_FUSE=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_SNTP=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_EFIDEBUG=y +CONFIG_CMD_RTC=y +CONFIG_CMD_TIME=y +CONFIG_CMD_GETTIME=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_HASH=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_NOWHERE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_ENV_RELOC_GD_ENV_ADDR=y +CONFIG_ENV_MMC_DEVICE_INDEX=1 +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_USE_ETHPRIME=y +CONFIG_ETHPRIME="eth0" +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SYS_RX_ETH_BUFFER=8 +CONFIG_SPL_DM=y +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_SPL_CLK=y +CONFIG_SPL_CLK_CCF=y +CONFIG_CLK_SCMI=y +CONFIG_SPL_CLK_SCMI=y +CONFIG_CLK_IMX95_BLKCTRL=y +CONFIG_DFU_MMC=y +CONFIG_DFU_RAM=y +CONFIG_SPL_FIRMWARE=y +# CONFIG_SCMI_AGENT_SMCCC is not set +CONFIG_IMX_RGPIO2P=y +CONFIG_DM_PCA953X=y +CONFIG_ADP5585_GPIO=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_IMX_LPI2C=y +CONFIG_IMX_MU_MBOX=y +CONFIG_SUPPORT_EMMC_BOOT=y +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_HS400_ES_SUPPORT=y +CONFIG_MMC_HS400_SUPPORT=y +CONFIG_FSL_USDHC=y +CONFIG_MTD=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_PHYLIB=y +CONFIG_PHY_AQUANTIA=y +CONFIG_PHY_REALTEK=y +CONFIG_DM_MDIO=y +CONFIG_MII=y +CONFIG_FSL_ENETC=y +CONFIG_PCIE_ECAM_GENERIC=y +CONFIG_PCIE_DW_IMX=y +CONFIG_PHY=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_PINCTRL_IMX_SCMI=y +CONFIG_POWER_DOMAIN=y +CONFIG_SCMI_POWER_DOMAIN=y +CONFIG_SPL_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_SPL_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_RTC=y +CONFIG_DM_SERIAL=y +CONFIG_FSL_LPUART=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_NXP_FSPI=y +CONFIG_ULP_WATCHDOG=y +CONFIG_LZO=y +CONFIG_BZIP2=y diff --git a/doc/board/nxp/imx95_evk.rst b/doc/board/nxp/imx95_evk.rst index 709992e016d..b8c3f4bed50 100644 --- a/doc/board/nxp/imx95_evk.rst +++ b/doc/board/nxp/imx95_evk.rst @@ -48,6 +48,7 @@ Note: srctree is U-Boot source directory $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.28-994fa14.bin $ sh firmware-imx-8.28-994fa14.bin --auto-accept $ cp firmware-imx-8.28-994fa14/firmware/ddr/synopsys/lpddr5*v202409.bin $(srctree) + $ cp firmware-imx-8.28-994fa14/firmware/ddr/synopsys/lpddr4x*v202409.bin $(srctree) Get and Build OEI Images -------------------------------------- @@ -65,7 +66,7 @@ branch: master $ git clone -b master https://github.com/nxp-imx/imx-oei.git $ cd imx-oei -i.MX95 A0 silicon version +i.MX95 A0 silicon version on 19x19 LPDDR5 EVK .. code-block:: bash @@ -75,13 +76,20 @@ i.MX95 A0 silicon version $ make board=mx95lp5 oei=tcm DEBUG=1 r=A0 all $ cp build/mx95lp5/tcm/oei-m33-tcm.bin $(srctree) -i.MX95 B0 silicon version +i.MX95 B0 silicon version on 19x19 LPDDR5 EVK .. code-block:: bash $ make board=mx95lp5 oei=ddr DEBUG=1 r=B0 all $ cp build/mx95lp5/ddr/oei-m33-ddr.bin $(srctree) +i.MX95 B0 silicon version on 15x15 LPDDR4X EVK + +.. code-block:: bash + + $ make board=mx95lp4x-15 oei=ddr DEBUG=1 r=B0 all + $ cp build/mx95lp4x-15/ddr/oei-m33-ddr.bin $(srctree) + Get and Build System Manager Image -------------------------------------- @@ -120,7 +128,7 @@ branch: lf_v2.12 Build the Bootloader Image -------------------------- -i.MX95 A0 silicon version +i.MX95 A0 silicon version on 19x19 LPDDR5 EVK .. code-block:: bash @@ -128,7 +136,7 @@ i.MX95 A0 silicon version $ make imx95_a0_19x19_evk_defconfig $ make -i.MX95 B0 silicon version +i.MX95 B0 silicon version on 19x19 LPDDR5 EVK .. code-block:: bash @@ -136,6 +144,14 @@ i.MX95 B0 silicon version $ make imx95_19x19_evk_defconfig $ make +i.MX95 B0 silicon version on 15x15 LPDDR4X EVK + +.. code-block:: bash + + $ export CROSS_COMPILE=aarch64-poky-linux- + $ make imx95_15x15_evk_defconfig + $ make + Copy imx-boot-imx95.bin to the MicroSD card: .. code-block:: bash diff --git a/include/configs/imx95_evk.h b/include/configs/imx95_evk.h index 2eebdadc51d..3d22740b3f4 100644 --- a/include/configs/imx95_evk.h +++ b/include/configs/imx95_evk.h @@ -15,9 +15,13 @@ #define CFG_SYS_SDRAM_BASE 0x90000000 #define PHYS_SDRAM 0x90000000 -/* Totally 16GB */ + #define PHYS_SDRAM_SIZE 0x70000000 /* 2GB - 256MB DDR */ -#define PHYS_SDRAM_2_SIZE 0x380000000 /* 14GB */ +#ifdef CONFIG_TARGET_IMX95_15X15_EVK +#define PHYS_SDRAM_2_SIZE 0x180000000 /* 6GB (Totally 8GB) */ +#else +#define PHYS_SDRAM_2_SIZE 0x380000000 /* 14GB (Totally 16GB) */ +#endif #define WDOG_BASE_ADDR WDG3_BASE_ADDR