summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Agner <stefan@agner.ch>2015-05-17 21:53:16 +0200
committerStefan Agner <stefan.agner@toradex.com>2015-05-28 16:58:36 +0200
commit4582732103393887b0e63a9fe572940909c23f8d (patch)
treeeba08214a6016814bf94ac8919f4784d96eba7aa
parentd1d416f272e840e8139aec911f89a70fe5523eb2 (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/Makefile20
-rw-r--r--arch/arm/imx-common/cmd_m4boot.c12
-rw-r--r--arch/arm/imx-common/vf610m4bootldr.S61
3 files changed, 92 insertions, 1 deletions
diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
index 175a36339d..64959fb4ae 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 67c4c4fa07..1e0168c97d 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 0000000000..991d31fa87
--- /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: