From ea47cbf5a8693a2e111f812d2b48be9703a489ec Mon Sep 17 00:00:00 2001 From: Ye Li Date: Mon, 14 Nov 2016 17:58:04 +0800 Subject: [PATCH] MLK-13450-7 mx7ulp: Add M4 core boot support when using single boot mode The single boot mode in MX7ULP will only boot up A7, the M4 is running in ROM by checking entry from SIM0 GP register. In this patch, We bind M4 image with u-boot.bin by allocating a section for m4 image. So the whole image (included M4 image) will be loaded by A7 ROM into DDR. Then when u-boot is up, it will try to load M4 image into TCML and boot it there. Since M4 image will not be relocated in u-boot codes, we must load it during board_f. Current implementation put it in arch_cpu_init to get M4 booted as quick as possible. We requires the M4 image with IVT head and padding embedded, not a RAW binary. The image should be same as what is used for M4 QSPI boot in dual boot mode. Signed-off-by: Ye Li (cherry picked from commit 04163dbd4f6190f310fff17b53b4bc7b8370ba89) (cherry picked from commit 81b5ea14493ef25a6cca22bc5651ec3e93e941f3) (cherry picked from commit 1e4414da2e9a671896af1af887ab710489a2007e) (cherry picked from commit b3a50e57aafe2830388d1295a8583c4e2515594b) (cherry picked from commit 2b9416b3dcd0eb85504aece94a603dc9aca6021e) (cherry picked from commit aadc312ee92c6f6ab2c427ca5eec2a7a02281e50) --- arch/arm/config.mk | 4 +++ arch/arm/cpu/u-boot.lds | 16 +++++++++++ arch/arm/mach-imx/mx7ulp/Kconfig | 6 ++++ arch/arm/mach-imx/mx7ulp/Makefile | 1 + arch/arm/mach-imx/mx7ulp/piggy_m4.S | 2 ++ arch/arm/mach-imx/mx7ulp/soc.c | 43 +++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+) create mode 100644 arch/arm/mach-imx/mx7ulp/piggy_m4.S diff --git a/arch/arm/config.mk b/arch/arm/config.mk index 4153f7e371..d3c8c6ae78 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -151,6 +151,10 @@ ifdef CONFIG_EFI_LOADER OBJCOPYFLAGS += -j .efi_runtime -j .efi_runtime_rel endif +ifdef CONFIG_IMX_M4_BIND +OBJCOPYFLAGS += -j .firmware_image +endif + ifneq ($(CONFIG_IMX_CONFIG),) ifdef CONFIG_SPL ifndef CONFIG_SPL_BUILD diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds index 0eb164d2e6..76f45d2a08 100644 --- a/arch/arm/cpu/u-boot.lds +++ b/arch/arm/cpu/u-boot.lds @@ -177,6 +177,22 @@ SECTIONS *(.__image_copy_end) } +#ifdef CONFIG_IMX_M4_BIND + .firmware_image_start : { + *(.__firmware_image_start) + } + + .firmware_image : { + KEEP(*(.firmware_image)) + } + + .firmware_image_end : { + *(.__firmware_image_end) + } + + . = ALIGN(4); +#endif + .rel_dyn_start : { *(.__rel_dyn_start) diff --git a/arch/arm/mach-imx/mx7ulp/Kconfig b/arch/arm/mach-imx/mx7ulp/Kconfig index 2ffac9cf7c..fcb1759953 100644 --- a/arch/arm/mach-imx/mx7ulp/Kconfig +++ b/arch/arm/mach-imx/mx7ulp/Kconfig @@ -12,6 +12,12 @@ config MX7ULP select HAS_CAAM bool +config IMX_M4_BIND + bool "Bind ULP M4 image to final u-boot" + help + Select this to bind a ULP M4 image to final u-boot image + User needs put the M4 image ulp_m4.bin under u-boot directory + choice prompt "MX7ULP board select" optional diff --git a/arch/arm/mach-imx/mx7ulp/Makefile b/arch/arm/mach-imx/mx7ulp/Makefile index adb8d7aecb..1b131dd28e 100644 --- a/arch/arm/mach-imx/mx7ulp/Makefile +++ b/arch/arm/mach-imx/mx7ulp/Makefile @@ -4,3 +4,4 @@ # obj-y := soc.o clock.o iomux.o pcc.o scg.o +obj-$(CONFIG_IMX_M4_BIND) += piggy_m4.o diff --git a/arch/arm/mach-imx/mx7ulp/piggy_m4.S b/arch/arm/mach-imx/mx7ulp/piggy_m4.S new file mode 100644 index 0000000000..b33e8422ea --- /dev/null +++ b/arch/arm/mach-imx/mx7ulp/piggy_m4.S @@ -0,0 +1,2 @@ + .section .firmware_image,#alloc + .incbin "ulp_m4.bin" diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c index adced013ce..9e214575ee 100644 --- a/arch/arm/mach-imx/mx7ulp/soc.c +++ b/arch/arm/mach-imx/mx7ulp/soc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -77,8 +78,46 @@ enum bt_mode get_boot_mode(void) return LOW_POWER_BOOT; } +#ifdef CONFIG_IMX_M4_BIND +char __firmware_image_start[0] __attribute__((section(".__firmware_image_start"))); +char __firmware_image_end[0] __attribute__((section(".__firmware_image_end"))); + +int mcore_early_load_and_boot(void) +{ + u32 *src_addr = (u32 *)&__firmware_image_start; + u32 *dest_addr = (u32 *)TCML_BASE; /*TCML*/ + u32 image_size = SZ_128K + SZ_64K; /* 192 KB*/ + u32 pc = 0, tag = 0; + + memcpy(dest_addr, src_addr, image_size); + + /* Set GP register to tell the M4 rom the image entry */ + /* We assume the M4 image has IVT head and padding which + * should be same as the one programmed into QSPI flash + */ + tag = *(dest_addr + 1024); + if (tag != 0x402000d1 && tag !=0x412000d1) + return -1; + + pc = *(dest_addr + 1025); + + writel(pc, SIM0_RBASE + 0x70); /*GP7*/ + + return 0; +} +#endif + int arch_cpu_init(void) { +#ifdef CONFIG_IMX_M4_BIND + int ret; + if (get_boot_mode() == SINGLE_BOOT) { + ret = mcore_early_load_and_boot(); + if (ret) + puts("Invalid M4 image, boot failed\n"); + } +#endif + #ifdef CONFIG_IMX_SEC_INIT /* Secure init function such RNG */ imx_sec_init(); @@ -244,6 +283,10 @@ int print_cpuinfo(void) case SINGLE_BOOT: default: printf("Single boot\n"); +#ifdef CONFIG_IMX_M4_BIND + if (readl(SIM0_RBASE + 0x70)) + printf("M4 start at 0x%x\n", readl(SIM0_RBASE + 0x70)); +#endif break; } -- 2.17.1