[PATCH v1 12/12] board: nxp: imx952_evk: Add i.MX952 15x15 lpddr4x board support

alice.guo
2026-02-05T15:17:29Z

From: Peng Fan <peng.fan@nxp.com>

Add support for i.MX952 15x15 lpddr4x board support.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Alice Guo <alice.guo@nxp.com>
---
arch/arm/mach-imx/Makefile | 2 +-
arch/arm/mach-imx/imx9/Kconfig | 14 ++
board/nxp/imx952_evk/Kconfig | 12 ++
board/nxp/imx952_evk/MAINTAINERS | 6 +
board/nxp/imx952_evk/Makefile | 14 ++
board/nxp/imx952_evk/imx952_evk.c | 297 ++++++++++++++++++++++++++++++++++++
board/nxp/imx952_evk/imx952_evk.env | 137 +++++++++++++++++
board/nxp/imx952_evk/spl.c | 115 ++++++++++++++
configs/imx952_evk_defconfig | 178 +++++++++++++++++++++
doc/board/nxp/imx952_evk.rst | 112 ++++++++++++++
doc/board/nxp/index.rst | 1 +
include/configs/imx952_evk.h | 31 ++++
12 files changed, 918 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0f6e737c0b9..bf6820de655 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -223,7 +223,7 @@ endif

ifeq ($(CONFIG_ARCH_IMX9)$(CONFIG_ARCH_IMX8ULP), y)

-ifneq ($(and $(CONFIG_BINMAN),$(or $(CONFIG_IMX95),$(CONFIG_IMX94))),)
+ifneq ($(and $(CONFIG_BINMAN),$(or $(CONFIG_IMX95),$(CONFIG_IMX94),$(CONFIG_IMX952))),)
SPL: spl/u-boot-spl.bin FORCE
$(call if_changed,mkimage)

diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig
index 716940930a6..2ba088c49c5 100644
--- a/arch/arm/mach-imx/imx9/Kconfig
+++ b/arch/arm/mach-imx/imx9/Kconfig
@@ -162,6 +162,19 @@ config TARGET_TORADEX_SMARC_IMX95
bool "Support Toradex SMARC iMX95"
select IMX95

+config TARGET_IMX952_EVK
+ bool "imx952_evk"
+ select CMD_REMOTEPROC
+ select IMX_SM_CPU
+ select IMX_SM_LMM
+ select IMX952
+ select REMOTEPROC_IMX
+ select REGMAP
+ select SYSCON
+ imply BOOTSTD_BOOTCOMMAND
+ imply BOOTSTD_FULL
+ imply OF_UPSTREAM
+
endchoice

source "board/nxp/imx91_evk/Kconfig"
@@ -175,5 +188,6 @@ source "board/variscite/imx93_var_som/Kconfig"
source "board/nxp/imx94_evk/Kconfig"
source "board/nxp/imx95_evk/Kconfig"
source "board/toradex/smarc-imx95/Kconfig"
+source "board/nxp/imx952_evk/Kconfig"

endif
diff --git a/board/nxp/imx952_evk/Kconfig b/board/nxp/imx952_evk/Kconfig
new file mode 100644
index 00000000000..96f01323aca
--- /dev/null
+++ b/board/nxp/imx952_evk/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_IMX952_EVK
+
+config SYS_BOARD
+ default "imx952_evk"
+
+config SYS_VENDOR
+ default "nxp"
+
+config SYS_CONFIG_NAME
+ default "imx952_evk"
+
+endif
diff --git a/board/nxp/imx952_evk/MAINTAINERS b/board/nxp/imx952_evk/MAINTAINERS
new file mode 100644
index 00000000000..cc004f9467e
--- /dev/null
+++ b/board/nxp/imx952_evk/MAINTAINERS
@@ -0,0 +1,6 @@
+i.MX952 EVK BOARD
+M: Alice Guo <alice.guo@nxp.com>
+S: Maintained
+F: board/nxp/imx952_evk/
+F: include/configs/imx952_evk.h
+F: configs/imx952_evk_defconfig
diff --git a/board/nxp/imx952_evk/Makefile b/board/nxp/imx952_evk/Makefile
new file mode 100644
index 00000000000..1581721dc78
--- /dev/null
+++ b/board/nxp/imx952_evk/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright 2025-2026 NXP
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+# Add include path for NXP device tree header files from Linux.
+ccflags-y += -I$(srctree)/dts/upstream/src/arm64/freescale/
+
+obj-y += imx952_evk.o
+
+ifdef CONFIG_SPL_BUILD
+obj-y += spl.o
+endif
diff --git a/board/nxp/imx952_evk/imx952_evk.c b/board/nxp/imx952_evk/imx952_evk.c
new file mode 100644
index 00000000000..8b4b2083a20
--- /dev/null
+++ b/board/nxp/imx952_evk/imx952_evk.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025-2026 NXP
+ */
+
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <env.h>
+#include <fdt_support.h>
+#include <imx952-power.h>
+#include <init.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+#include <scmi_agent.h>
+#include <usb.h>
+
+#define PD_HSIO_TOP IMX952_PD_HSIO_TOP
+#define PD_NETC IMX952_PD_NETC
+#define PD_DISPLAY IMX952_PD_DISPLAY
+#define PD_CAMERA IMX952_PD_CAMERA
+
+#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
+#define IMX_BOOT_IMAGE_GUID \
+ EFI_GUID(0x58a661f3, 0xe7c7, 0x4173, 0x80, 0x21, \
+ 0xa3, 0x1b, 0x95, 0xc8, 0x6e, 0x9b)
+
+struct efi_fw_image fw_images[] = {
+ {
+ .image_type_id = IMX_BOOT_IMAGE_GUID,
+ .fw_name = u"IMX952-EVK-RAW",
+ .image_index = 1,
+ },
+};
+
+struct efi_capsule_update_info update_info = {
+ .dfu_string = "mmc 0=flash-bin raw 0 0x2000 mmcpart 1",
+ .num_images = ARRAY_SIZE(fw_images),
+ .images = fw_images,
+};
+#endif /* EFI_HAVE_CAPSULE_SUPPORT */
+
+int board_early_init_f(void)
+{
+ /* UART1: A55, UART2: M33, UART3: M7 */
+ init_uart_clk(0);
+
+ return 0;
+}
+
+#ifdef CONFIG_USB_TCPC
+struct tcpc_port port;
+struct tcpc_port_config port_config = {
+ .i2c_bus = 6, /* i2c7 */
+ .addr = 0x50,
+ .port_type = TYPEC_PORT_DRP,
+ .disable_pd = true,
+};
+
+static int setup_typec(void)
+{
+ int ret;
+
+ debug("tcpc_init port 1\n");
+ ret = tcpc_init(&port, port_config, NULL);
+ if (ret) {
+ printf("%s: tcpc port init failed, err=%d\n",
+ __func__, ret);
+ }
+
+ return ret;
+}
+#endif
+
+static int imx9_scmi_power_domain_enable(u32 domain, bool enable)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
+ if (ret)
+ return ret;
+
+ return scmi_pwd_state_set(dev, 0, domain, enable ? 0 : BIT(30));
+}
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+ int ret = 0;
+
+ if (index == 0 && init == USB_INIT_DEVICE) {
+ ret = imx9_scmi_power_domain_enable(PD_HSIO_TOP, true);
+ if (ret) {
+ printf("SCMI_POWWER_STATE_SET Failed for USB\n");
+ return ret;
+ }
+ } else if (index == 0 && init == USB_INIT_HOST) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+ int ret = 0;
+
+ if (index == 0 && init == USB_INIT_HOST) {
+#ifdef CONFIG_USB_TCPC
+ ret = tcpc_disable_src_vbus(&port);
+#endif
+ }
+
+ return ret;
+}
+
+static void netc_phy_rst(const char *gpio_name, const char *label)
+{
+ int ret;
+ struct gpio_desc desc;
+
+ /* ENET_RST_B */
+ ret = dm_gpio_lookup_name(gpio_name, &desc);
+ if (ret) {
+ printf("%s lookup %s failed ret = %d\n", __func__, gpio_name, ret);
+ return;
+ }
+
+ ret = dm_gpio_request(&desc, label);
+ if (ret) {
+ printf("%s request %s failed ret = %d\n", __func__, label, ret);
+ return;
+ }
+
+ /* assert the ENET_RST_B */
+ dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE | GPIOD_ACTIVE_LOW);
+ udelay(10000);
+ dm_gpio_set_value(&desc, 0); /* deassert the ENET_RST_B */
+ udelay(80000);
+}
+
+void netc_init(void)
+{
+ int ret;
+
+ ret = imx9_scmi_power_domain_enable(PD_NETC, false);
+ udelay(10000);
+
+ /* Power up the NETC MIX. */
+ ret = imx9_scmi_power_domain_enable(PD_NETC, true);
+ if (ret) {
+ printf("SCMI_POWWER_STATE_SET Failed for NETC MIX\n");
+ return;
+ }
+
+ netc_phy_rst("i2c6_io@21_13", "ENET1_RST_B");
+
+ pci_init();
+}
+
+static void pcie_setup(void)
+{
+ int ret;
+ struct udevice *dev;
+
+ ret = regulator_get_by_devname("regulator-m2-pwr", &dev);
+ if (ret) {
+ printf("Get regulator-m2-pwr regulator failed %d\n", ret);
+ return;
+ }
+
+ ret = regulator_set_enable_if_allowed(dev, true);
+ if (ret) {
+ printf("Enable regulator-m2-pwr regulator %d\n", ret);
+ return;
+ }
+}
+
+void lvds_backlight_on(void)
+{
+ /* None */
+}
+
+int board_init(void)
+{
+ int ret;
+
+ ret = imx9_scmi_power_domain_enable(PD_HSIO_TOP, true);
+ if (ret) {
+ printf("SCMI_POWWER_STATE_SET Failed for USB\n");
+ return ret;
+ }
+
+ imx9_scmi_power_domain_enable(PD_DISPLAY, false);
+ imx9_scmi_power_domain_enable(PD_CAMERA, false);
+
+#if defined(CONFIG_USB_TCPC)
+ setup_typec();
+#endif
+
+ pcie_setup();
+
+ netc_init();
+
+ lvds_backlight_on();
+
+ return 0;
+}
+
+int board_late_init(void)
+{
+ if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
+ board_late_mmc_env_init();
+
+ env_set("sec_boot", "no");
+#ifdef CONFIG_AHAB_BOOT
+ env_set("sec_boot", "yes");
+#endif
+
+ return 0;
+}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+ char *p, *b, *s;
+ char *token = NULL;
+ int i, ret = 0;
+ u64 base[CONFIG_NR_DRAM_BANKS] = {0};
+ u64 size[CONFIG_NR_DRAM_BANKS] = {0};
+
+ p = env_get("jh_root_mem");
+ if (!p)
+ return 0;
+
+ i = 0;
+ token = strtok(p, ",");
+ while (token) {
+ if (i >= CONFIG_NR_DRAM_BANKS) {
+ printf("Error: The number of size@base exceeds CONFIG_NR_DRAM_BANKS.\n");
+ return -EINVAL;
+ }
+
+ b = token;
+ s = strsep(&b, "@");
+ if (!s) {
+ printf("The format of jh_root_mem is size@base[,size@base...].\n");
+ return -EINVAL;
+ }
+ base[i] = simple_strtoull(b, NULL, 16);
+ size[i] = simple_strtoull(s, NULL, 16);
+ token = strtok(NULL, ",");
+ i++;
+ }
+
+ ret = fdt_fixup_memory_banks(blob, base, size, CONFIG_NR_DRAM_BANKS);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+#endif
+
+void board_quiesce_devices(void)
+{
+ int ret;
+ struct uclass *uc_dev;
+
+ ret = imx9_scmi_power_domain_enable(PD_HSIO_TOP, false);
+ if (ret) {
+ printf("%s: Failed for HSIO MIX: %d\n", __func__, ret);
+ return;
+ }
+
+ ret = imx9_scmi_power_domain_enable(PD_NETC, false);
+ if (ret) {
+ printf("%s: Failed for NETC MIX: %d\n", __func__, ret);
+ return;
+ }
+
+ ret = uclass_get(UCLASS_SPI_FLASH, &uc_dev);
+ if (uc_dev)
+ ret = uclass_destroy(uc_dev);
+ if (ret)
+ printf("couldn't remove SPI FLASH devices\n");
+}
+
+#ifdef CONFIG_FSL_FASTBOOT
+#ifdef CONFIG_ANDROID_RECOVERY
+int is_recovery_key_pressing(void)
+{
+ return 0;
+}
+#endif /*CONFIG_ANDROID_RECOVERY*/
+#endif /*CONFIG_FSL_FASTBOOT*/
diff --git a/board/nxp/imx952_evk/imx952_evk.env b/board/nxp/imx952_evk/imx952_evk.env
new file mode 100644
index 00000000000..6ecaf9724c1
--- /dev/null
+++ b/board/nxp/imx952_evk/imx952_evk.env
@@ -0,0 +1,137 @@
+#ifdef CONFIG_ANDROID_SUPPORT
+splashpos=m,m
+splashimage=0x9FFF0000
+emmc_dev=0
+sd_dev=1
+#else
+
+#ifdef CONFIG_AHAB_BOOT
+sec_boot=yes
+#else
+sec_boot=no
+#endif
+
+jh_root_dtb=imx952-evk-root.dtb
+jh_mmcboot=setenv fdtfile ${jh_root_dtb};
+ setenv jh_clk kvm.enable_virt_at_load=false cpuidle.off=1 clk_ignore_unused kvm-arm.mode=nvhe;
+ setenv jh_root_mem 0x58000000@0x90000000,0x300000000@0x180000000;
+ if run loadimage; then
+ run mmcboot;
+ else run jh_netboot; fi;
+jh_netboot=setenv fdtfile ${jh_root_dtb};
+ setenv jh_root_mem 0x58000000@0x90000000,0x300000000@0x180000000;
+ setenv jh_clk kvm.enable_virt_at_load=false cpuidle.off=1 clk_ignore_unused kvm-arm.mode=nvhe; run netboot;
+
+domu-android-auto=no
+xenhyper_bootargs=console=dtuart dom0_mem=4096M dom0_max_vcpus=2 pci-passthrough=on
+xenlinux_bootargs=
+xenlinux_console=hvc0 earlycon=xen
+xenlinux_addr=0x9c000000
+dom0fdt_file=CONFIG_DEFAULT_FDT_FILE
+xenboot_common=${get_cmd} ${loadaddr} xen;
+ ${get_cmd} ${fdt_addr} ${dom0fdt_file};
+ ${get_cmd} ${xenlinux_addr} ${image};
+ fdt addr ${fdt_addr};
+ fdt resize 256;
+ fdt mknode /chosen module@0;
+ fdt set /chosen/module@0 reg <0x00000000 ${xenlinux_addr} 0x00000000 0x${filesize}>;
+ fdt set /chosen/module@0 bootargs "${bootargs} ${xenlinux_bootargs}";
+ fdt set /soc/bus@49000000/iommu@490d0000 status disabled;
+ fdt set /chosen/module@0 compatible "xen,linux-zimage" "xen,multiboot-module";
+ setenv bootargs ${xenhyper_bootargs};
+ booti ${loadaddr} - ${fdt_addr};
+xennetboot=setenv get_cmd dhcp;setenv console ${xenlinux_console};setenv jh_clk kvm.enable_virt_at_load=false clk_ignore_unused;run netargs;run xenboot_common;
+xenmmcboot=setenv get_cmd "fatload mmc ${mmcdev}:${mmcpart}";setenv console ${xenlinux_console};setenv jh_clk kvm.enable_virt_at_load=false clk_ignore_unused;run mmcargs;run xenboot_common;
+
+sr_ir_v2_cmd=cp.b ${fdtcontroladdr} ${fdt_addr_r} 0x10000; fdt addr ${fdt_addr_r};
+ fdt set /soc/bus@44000000/mailbox@445b0000/sram@445b1000/scmi-sram-section@0 reg <0x00000000 0x00000080>;
+ fdt rm /soc/mailbox@47530000;
+ fdt rm /soc/usb@4c010010;
+
+initrd_addr=0x93800000
+emmc_dev=0
+sd_dev=1
+scriptaddr=0x93500000
+kernel_addr_r=CONFIG_SYS_LOAD_ADDR
+image=Image
+splashimage=0xA0000000
+console=ttyLP0,115200 earlycon
+fdt_addr_r=0x93000000
+fdt_addr=0x93000000
+cntr_addr=0xA8000000
+cntr_file=os_cntr_signed.bin
+boot_fit=no
+fdtfile=CONFIG_DEFAULT_FDT_FILE
+bootm_size=0x10000000
+mmcdev=CONFIG_SYS_MMC_ENV_DEV
+mmcpart=1
+mmcroot=/dev/mmcblk1p2 rootwait rw
+mmcautodetect=yes
+mmcargs=setenv bootargs ${jh_clk} ${mcore_args} console=${console} root=${mmcroot}
+prepare_mcore=setenv mcore_args pd_ignore_unused;
+loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
+bootscript=echo Running bootscript from mmc ...; source
+loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
+loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile}
+loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} ${cntr_file}
+auth_os=booti ${cntr_addr}
+boot_os=booti ${loadaddr} - ${fdt_addr_r};
+mmcboot=echo Booting from mmc ...;
+ run mmcargs;
+ if test ${sec_boot} = yes; then
+ run auth_os;
+ else
+ if test ${boot_fit} = yes || test ${boot_fit} = try; then
+ bootm ${loadaddr};
+ else
+ if run loadfdt; then
+ run boot_os;
+ else
+ echo WARN: Cannot load the DT;
+ fi;
+ fi;
+ fi;
+netargs=setenv bootargs ${jh_clk} ${mcore_args} console=${console} root=/dev/nfs
+ ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
+netboot=echo Booting from net ...;
+ run netargs;
+ if test ${ip_dyn} = yes; then
+ setenv get_cmd dhcp;
+ else
+ setenv get_cmd tftp;
+ fi;
+ if test ${sec_boot} = yes; then
+ ${get_cmd} ${cntr_addr} ${cntr_file};
+ run auth_os;
+ else
+ ${get_cmd} ${loadaddr} ${image};
+ if test ${boot_fit} = yes || test ${boot_fit} = try; then
+ bootm ${loadaddr};
+ else
+ if ${get_cmd} ${fdt_addr_r} ${fdtfile}; then
+ run boot_os;
+ else
+ echo WARN: Cannot load the DT;
+ fi;
+ fi;
+ fi;
+bsp_bootcmd=echo Running BSP bootcmd ...;
+ mmc dev ${mmcdev}; if mmc rescan; then
+ if run loadbootscript; then
+ run bootscript;
+ else
+ if test ${sec_boot} = yes; then
+ if run loadcntr; then
+ run mmcboot;
+ else run netboot;
+ fi;
+ else
+ if run loadimage; then
+ run mmcboot;
+ else run netboot;
+ fi;
+ fi;
+ fi;
+ fi;
+
+#endif
diff --git a/board/nxp/imx952_evk/spl.c b/board/nxp/imx952_evk/spl.c
new file mode 100644
index 00000000000..d36c3a46b5e
--- /dev/null
+++ b/board/nxp/imx952_evk/spl.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025-2026 NXP
+ */
+
+#include <asm/arch/mu.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/mach-imx/ele_api.h>
+#include <asm/sections.h>
+#include <hang.h>
+#include <init.h>
+#include <linux/delay.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int spl_board_boot_device(enum boot_device boot_dev_spl)
+{
+ switch (boot_dev_spl) {
+ case SD1_BOOT:
+ case MMC1_BOOT:
+ return BOOT_DEVICE_MMC1;
+ case SD2_BOOT:
+ case MMC2_BOOT:
+ return BOOT_DEVICE_MMC2;
+ case USB_BOOT:
+ case USB2_BOOT:
+ return BOOT_DEVICE_BOARD;
+ case QSPI_BOOT:
+ return BOOT_DEVICE_SPI;
+ default:
+ return BOOT_DEVICE_NONE;
+ }
+}
+
+void spl_board_init(void)
+{
+ int ret;
+
+ puts("Normal Boot\n");
+
+ ret = ele_start_rng();
+ if (ret)
+ printf("Fail to start RNG: %d\n", ret);
+}
+
+static void xspi_nor_reset(void)
+{
+ int ret;
+ struct gpio_desc desc;
+
+ ret = dm_gpio_lookup_name("GPIO5_11", &desc);
+ if (ret) {
+ printf("%s lookup GPIO5_11 failed ret = %d\n", __func__, ret);
+ return;
+ }
+
+ ret = dm_gpio_request(&desc, "XSPI_RST_B");
+ if (ret) {
+ printf("%s request XSPI_RST_B failed ret = %d\n", __func__, ret);
+ return;
+ }
+
+ /* assert the XSPI_RST_B */
+ dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE | GPIOD_ACTIVE_LOW);
+ udelay(200); /* 50 ns at least, so use 200ns */
+ dm_gpio_set_value(&desc, 0); /* deassert the XSPI_RST_B */
+}
+
+void board_init_f(ulong dummy)
+{
+ int ret;
+
+ /* Clear the BSS. */
+ memset(__bss_start, 0, __bss_end - __bss_start);
+
+#ifdef CONFIG_SPL_RECOVER_DATA_SECTION
+ if (IS_ENABLED(CONFIG_SPL_BUILD))
+ spl_save_restore_data();
+#endif
+
+ timer_init();
+
+ /* Need dm_init() to run before any SCMI calls can be made. */
+ spl_early_init();
+
+ /* Need enable SCMI drivers and ELE driver before enabling console */
+ ret = imx9_probe_mu();
+ if (ret)
+ hang(); /* if MU not probed, nothing can output, just hang here */
+
+ arch_cpu_init();
+
+ board_early_init_f();
+
+ preloader_console_init();
+
+ debug("SOC: 0x%x\n", gd->arch.soc_rev);
+ debug("LC: 0x%x\n", gd->arch.lifecycle);
+
+ get_reset_reason(true, false);
+
+ xspi_nor_reset();
+
+ board_init_r(NULL, 0);
+}
+
+#ifdef CONFIG_ANDROID_SUPPORT
+int board_get_emmc_id(void)
+{
+ return 0;
+}
+#endif
diff --git a/configs/imx952_evk_defconfig b/configs/imx952_evk_defconfig
new file mode 100644
index 00000000000..59de9ee0333
--- /dev/null
+++ b/configs/imx952_evk_defconfig
@@ -0,0 +1,178 @@
+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_ENV_SOURCE_FILE="imx952_evk"
+CONFIG_NR_DRAM_BANKS=3
+CONFIG_SF_DEFAULT_SPEED=200000000
+CONFIG_ENV_SIZE=0x4000
+CONFIG_ENV_OFFSET=0x700000
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="freescale/imx952-evk"
+CONFIG_TARGET_IMX952_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_OF_LIBFDT_ASSUME_MASK=0x0
+CONFIG_SPL=y
+CONFIG_SPL_RECOVER_DATA_SECTION=y
+CONFIG_PCI=y
+CONFIG_OF_BOARD_FIXUP=y
+CONFIG_SYS_MEMTEST_START=0x90000000
+CONFIG_SYS_MEMTEST_END=0xA0000000
+CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_BOOTCOMMAND="bootflow scan -l; run bsp_bootcmd"
+CONFIG_DEFAULT_FDT_FILE="imx952-evk.dtb"
+CONFIG_SYS_CBSIZE=2048
+CONFIG_SYS_PBSIZE=2074
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_SPL_MAX_SIZE=0x30000
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+# 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_DOMAIN=y
+CONFIG_SPL_THERMAL=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_OPTEE_RPMB=y
+CONFIG_CMD_OPTEE=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
+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_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_USE_ETHPRIME=y
+CONFIG_ETHPRIME="eth0"
+# CONFIG_BOOTDEV_ETH is not set
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SYS_RX_ETH_BUFFER=8
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_SPL_CLK_CCF=y
+CONFIG_CLK_CCF=y
+CONFIG_CLK_SCMI=y
+CONFIG_SPL_CLK_SCMI=y
+CONFIG_DFU_MMC=y
+CONFIG_DFU_RAM=y
+CONFIG_SPL_FIRMWARE=y
+# CONFIG_SCMI_AGENT_SMCCC is not set
+# CONFIG_SCMI_AGENT_OPTEE 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_RPMB=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_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_SOFT_RESET=y
+CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_MT35XU=y
+CONFIG_PHYLIB=y
+CONFIG_PHY_AQUANTIA=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DM_MDIO=y
+CONFIG_MII=y
+CONFIG_FSL_ENETC=y
+CONFIG_NVME_PCI=y
+CONFIG_PCIE_ECAM_GENERIC=y
+CONFIG_PCIE_DW_IMX=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_RTC_EMULATION=y
+CONFIG_DM_SERIAL=y
+CONFIG_FSL_LPUART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
+CONFIG_SYSRESET_PSCI=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_DM_THERMAL=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_GADGET=y
+CONFIG_SPL_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1fc9
+CONFIG_USB_GADGET_PRODUCT_NUM=0x0152
+CONFIG_SDP_LOADADDR=0x90400000
+CONFIG_SPL_USB_SDP_SUPPORT=y
+CONFIG_ULP_WATCHDOG=y
+CONFIG_LZO=y
+CONFIG_BZIP2=y
diff --git a/doc/board/nxp/imx952_evk.rst b/doc/board/nxp/imx952_evk.rst
new file mode 100644
index 00000000000..9f20db2403f
--- /dev/null
+++ b/doc/board/nxp/imx952_evk.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+imx952_evk
+=======================
+
+U-Boot for the NXP i.MX952 15x15 LPDDR4X EVK board
+
+Quick Start
+-----------
+
+- Get ahab-container.img
+- Get DDR PHY Firmware Images
+- Get and Build OEI Images
+- Get and Build System Manager Image
+- Get and Build the ARM Trusted Firmware
+- Build the Bootloader Image
+- Boot
+
+Get ahab-container.img
+--------------------------------------
+
+Note: srctree is U-Boot source directory
+
+.. code-block:: bash
+
+ $ wget https://nl2-nxrm.sw.nxp.com/repository/IMX_Yocto_Internal_Mirror_Recent/firmware-ele-imx-2.0.5-50c4793.bin
+ $ sh firmware-ele-imx-2.0.5-50c4793.bin --auto-accept
+ $ cp firmware-ele-imx-2.0.5-50c4793/mx952a0-ahab-container.img $(srctree)
+
+Get DDR PHY Firmware Images
+--------------------------------------
+
+Note: srctree is U-Boot source directory
+
+.. code-block:: bash
+
+ $ wget https://nl2-nxrm.sw.nxp.com/repository/IMX_Yocto_Internal_Mirror_Recent/firmware-imx-8.32-c0491e4.bin
+ $ sh firmware-imx-8.32-c0491e4.bin --auto-accept
+ $ cp firmware-imx-8.32-c0491e4/firmware/ddr/synopsys/lpddr4x*v202409.bin $(srctree)
+
+Get and Build OEI Images
+--------------------------------------
+
+Note: srctree is U-Boot source directory
+Get OEI from: https://github.com/nxp-imx/imx-oei
+branch: lf-6.18.2-imx952-er1
+
+.. code-block:: bash
+
+ $ sudo apt -y install make gcc g++-multilib srecord
+ $ wget https://developer.arm.com/-/media/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
+ $ tar xvf arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
+ $ export TOOLS=$PWD
+ $ git clone https://github.com/nxp-imx/imx-oei/ -b lf-6.18.2-imx952-er1
+ $ cd imx-oei
+ $ make board=mx952lp4x-15 oei=ddr DEBUG=1 all
+ $ cp build/mx952lp4x-15/ddr/oei-m33-ddr.bin $(srctree)
+
+Get and Build System Manager Image
+--------------------------------------
+
+Note: srctree is U-Boot source directory
+Get System Manager from: https://github.com/nxp-imx/imx-sm
+branch: lf-6.18.2-imx952-er1
+
+.. code-block:: bash
+
+ $ sudo apt -y install make gcc g++-multilib srecord
+ $ wget https://developer.arm.com/-/media/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
+ $ tar xvf arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi.tar.xz
+ $ export TOOLS=$PWD
+ $ git clone https://github.com/nxp-imx/imx-sm/ -b lf-6.18.2-imx952-er1
+ $ cd imx-sm
+ $ make config=mx952evk all
+ $ cp build/mx952evk/m33_image.bin $(srctree)
+
+Get and Build the ARM Trusted Firmware
+--------------------------------------
+
+Note: srctree is U-Boot source directory
+Get ATF from: https://github.com/nxp-imx/imx-atf/
+branch: lf-6.18.2-imx952-er1
+
+.. code-block:: bash
+
+ $ export CROSS_COMPILE=aarch64-poky-linux-
+ $ unset LDFLAGS
+ $ unset AS
+ $ git clone https://github.com/nxp-imx/imx-atf/ -b lf-6.18.2-imx952-er1
+ $ cd imx-atf
+ $ make PLAT=imx952 bl31
+ $ cp build/imx952/release/bl31.bin $(srctree)
+
+Build the Bootloader Image
+--------------------------
+
+.. code-block:: bash
+
+ $ export CROSS_COMPILE=aarch64-poky-linux-
+ $ make imx952_evk_defconfig
+ $ make
+
+Copy flash.bin to the MicroSD card:
+
+.. code-block:: bash
+
+ $ sudo dd if=flash.bin of=/dev/sd[x] bs=1k seek=32 conv=fsync
+
+Boot
+----
+
+Set i.MX952 boot device to MicroSD card
diff --git a/doc/board/nxp/index.rst b/doc/board/nxp/index.rst
index 01d3468a47d..8cd24aecf33 100644
--- a/doc/board/nxp/index.rst
+++ b/doc/board/nxp/index.rst
@@ -19,6 +19,7 @@ NXP Semiconductors
imx93_frdm
imx943_evk
imx95_evk
+ imx952_evk
imxrt1020-evk
imxrt1050-evk
imxrt1170-evk
diff --git a/include/configs/imx952_evk.h b/include/configs/imx952_evk.h
new file mode 100644
index 00000000000..dadc883027f
--- /dev/null
+++ b/include/configs/imx952_evk.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2025-2026 NXP
+ */
+
+#ifndef __IMX952_EVK_H
+#define __IMX952_EVK_H
+
+#include <linux/sizes.h>
+#include <linux/stringify.h>
+#include <asm/arch/imx-regs.h>
+
+#define CFG_SYS_INIT_RAM_ADDR 0x90000000
+#define CFG_SYS_INIT_RAM_SIZE 0x200000
+
+#define CFG_SYS_SDRAM_BASE 0x90000000
+#define PHYS_SDRAM 0x90000000
+
+#define PHYS_SDRAM_SIZE 0x70000000 /* 2GB - 256MB DDR */
+#define PHYS_SDRAM_2_SIZE 0x380000000 /* 14GB */
+
+#define CFG_SYS_SECURE_SDRAM_BASE 0x8A000000 /* Secure DDR region for A55, SPL could use first 2MB */
+#define CFG_SYS_SECURE_SDRAM_SIZE 0x06000000
+
+#define WDOG_BASE_ADDR WDG3_BASE_ADDR
+
+#ifdef CONFIG_ANDROID_SUPPORT
+#include "imx952_evk_android.h"
+#endif
+
+#endif

--
2.43.0