diff options
author | Stefan Agner <stefan@agner.ch> | 2015-05-17 21:53:16 +0200 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2015-05-28 16:58:36 +0200 |
commit | 4582732103393887b0e63a9fe572940909c23f8d (patch) | |
tree | eba08214a6016814bf94ac8919f4784d96eba7aa | |
parent | d1d416f272e840e8139aec911f89a70fe5523eb2 (diff) |
imx-common: include mini-loader vf610m4bootldr
Include vf610m4bootldr, a mini boot loader for the Cortex-M4 CPU
inside Freescale Vybrid SoC. The mini loader enables caches and
copies the pointer to the device tree from the platform specific
argument register (PERSISTENT_ARG1) to the Cortex-M4 r2 register,
where the Linux kernel expects the pointer. The mini loader hence
essentially takes over the parts of the m4boot command which can
not be done from the Cortex-A5 main CPU.
-rw-r--r-- | arch/arm/imx-common/Makefile | 20 | ||||
-rw-r--r-- | arch/arm/imx-common/cmd_m4boot.c | 12 | ||||
-rw-r--r-- | arch/arm/imx-common/vf610m4bootldr.S | 61 |
3 files changed, 92 insertions, 1 deletions
diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile index 175a36339d0..64959fb4aed 100644 --- a/arch/arm/imx-common/Makefile +++ b/arch/arm/imx-common/Makefile @@ -24,6 +24,26 @@ obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o endif ifeq ($(SOC),$(filter $(SOC),vf610)) obj-y += ddrmc-vf610.o + +# The mini boot loader for Linux on the Cortex-M4 runs on ARMv7-M +# architecture, hence force ARMv7-M architecture. Use objcopy with +# binary-architecture (-B) to include the mini loader as binary blob +quiet_cmd_ccm4_s_S = M4CC $@ +cmd_ccm4_s_S = $(CC) -Wall -march=armv7-m -mthumb -c -o $@ $< +arch/arm/imx-common/vf610m4bootldr.o: arch/arm/imx-common/vf610m4bootldr.S + $(call if_changed,ccm4_s_S) + +quiet_cmd_objcopym4 = OBJCOPY $@ +cmd_objcopym4 = $(OBJCOPY) -O binary $< $@ +arch/arm/imx-common/vf610m4bootldr: arch/arm/imx-common/vf610m4bootldr.o + $(call if_changed,objcopym4) + +quiet_cmd_objcopybinm4 = OBJCOPY $@ +cmd_objcopybinm4 = $(OBJCOPY) -I binary -O elf32-littlearm -B arm $< $@ +arch/arm/imx-common/vf610m4bootldrbin.o: arch/arm/imx-common/vf610m4bootldr + $(call if_changed,objcopybinm4) + +obj-$(CONFIG_CMD_M4BOOT) += vf610m4bootldrbin.o endif obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o diff --git a/arch/arm/imx-common/cmd_m4boot.c b/arch/arm/imx-common/cmd_m4boot.c index 67c4c4fa073..1e0168c97d5 100644 --- a/arch/arm/imx-common/cmd_m4boot.c +++ b/arch/arm/imx-common/cmd_m4boot.c @@ -12,6 +12,7 @@ #include <asm/arch/crm_regs.h> #include <asm/io.h> #include <image.h> +#include <inttypes.h> #ifndef CONFIG_SYS_FDT_PAD #define CONFIG_SYS_FDT_PAD 0x3000 @@ -21,11 +22,20 @@ DECLARE_GLOBAL_DATA_PTR; #define CCM_CCOWR_START 0x00015a5a +extern unsigned char _binary_arch_arm_imx_common_vf610m4bootldr_start; +extern unsigned char _binary_arch_arm_imx_common_vf610m4bootldr_end; + static void boot_startm4_linux(bootm_headers_t *images) { struct src *src = (struct src *)SRC_BASE_ADDR; struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; - ulong ep_loader = images->ep - 0x80; + int size = &_binary_arch_arm_imx_common_vf610m4bootldr_end - + &_binary_arch_arm_imx_common_vf610m4bootldr_start; + ulong ep_loader = images->ep - size; + + /* Copy the Linux mini boot loader just in front of the image... */ + memcpy((void *)(images->os.image_start - size), + &_binary_arch_arm_imx_common_vf610m4bootldr_start, size); printf("Booting Cortex-M4 @0x%08lx\n", ep_loader); diff --git a/arch/arm/imx-common/vf610m4bootldr.S b/arch/arm/imx-common/vf610m4bootldr.S new file mode 100644 index 00000000000..991d31fa872 --- /dev/null +++ b/arch/arm/imx-common/vf610m4bootldr.S @@ -0,0 +1,61 @@ +/* + * Freescale Vybrid VF6xx M4 boot loader + * + * Enable PC/PS-Bus cache and get device tree pointer from Vybrid specific + * argument register (PERSISTENT_ARG1) + * + * Copyright (c) 2014-2015 Stefan Agner <stefan@agner.ch> + * + */ + +#define LMEM_PC_BASE 0xe0082000 +#define LMEM_PS_BASE 0xe0082800 +#define LMEM_PXCCR 0x0 +#define SRC_BASE 0x4006e000 +#define SRC_GPR2 0x28 +#define SRC_GPR3 0x2c + .thumb + .align +main: + .macro invalidate_cache, base + .local invalidate_cache + /* GO, INVW1 & INVW0 */ + mov r3, #0x85 + lsl r3, r3, #24 + + /* ENCACHE */ + mov r1, #0x1 + orr r3, r1 + str r3, [ \base, #LMEM_PXCCR ] + + ldr r3, =0x1 + lsl r3, r3, #31 +1: + ldr r2, [ \base, #LMEM_PXCCR ] + and r2, r2, r3 + bne 1b + .endm + + ldr r0, lmem_ps_base + invalidate_cache r0 + ldr r0, lmem_pc_base + invalidate_cache r0 + + ldr r0, src_base + ldr r1, machine_id @ Machine ID + ldr r2, [ r0, #SRC_GPR3 ] @ DT pointer from argument register + mov r0, #0x0 + b end + + .align + +machine_id: + .long 0xffffffff +src_base: + .long SRC_BASE +lmem_pc_base: + .long LMEM_PC_BASE +lmem_ps_base: + .long LMEM_PS_BASE + .align 7 +end: |