summaryrefslogtreecommitdiffstats
path: root/arch/arm/lib
diff options
context:
space:
mode:
authorrev13@wp.pl <rev13@wp.pl>2015-03-01 12:44:39 +0100
committerTom Rini <trini@konsulko.com>2015-04-22 12:14:55 -0400
commit12d8a729137ec58107236c472ddb14a819e7bd0b (patch)
tree9d4f065d21466e06071d29b1b86eb6d185f0dffb /arch/arm/lib
parent5d27223ea5424fc157c8ac0afb236bc8cfcd1772 (diff)
downloadtalos-obmc-uboot-12d8a729137ec58107236c472ddb14a819e7bd0b.tar.gz
talos-obmc-uboot-12d8a729137ec58107236c472ddb14a819e7bd0b.zip
ARM: Add ARMv7-M support
Signed-off-by: Kamil Lulko <rev13@wp.pl>
Diffstat (limited to 'arch/arm/lib')
-rw-r--r--arch/arm/lib/Makefile8
-rw-r--r--arch/arm/lib/crt0.S30
-rw-r--r--arch/arm/lib/interrupts_m.c95
-rw-r--r--arch/arm/lib/relocate.S13
-rw-r--r--arch/arm/lib/vectors_m.S57
5 files changed, 201 insertions, 2 deletions
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index da8ed72a11..0e1ad0e3dd 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -8,7 +8,9 @@
lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _ashldi3.o _ashrdi3.o _divsi3.o \
_lshrdi3.o _modsi3.o _udivsi3.o _umodsi3.o div0.o
-ifdef CONFIG_ARM64
+ifdef CONFIG_CPU_V7M
+obj-y += vectors_m.o crt0.o
+else ifdef CONFIG_ARM64
obj-y += crt0_64.o
else
obj-y += vectors.o crt0.o
@@ -36,7 +38,9 @@ obj-$(CONFIG_SEMIHOSTING) += semihosting.o
obj-y += sections.o
obj-y += stack.o
-ifdef CONFIG_ARM64
+ifdef CONFIG_CPU_V7M
+obj-y += interrupts_m.o
+else ifdef CONFIG_ARM64
obj-y += gic_64.o
obj-y += interrupts_64.o
else
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index 92d37324d3..afd4f102dc 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -9,6 +9,9 @@
#include <config.h>
#include <asm-offsets.h>
#include <linux/linkage.h>
+#ifdef CONFIG_CPU_V7M
+#include <asm/armv7m.h>
+#endif
/*
* This file handles the target-independent stages of the U-Boot
@@ -66,15 +69,30 @@ ENTRY(_main)
#else
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
+#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
+ mov r3, sp
+ bic r3, r3, #7
+ mov sp, r3
+#else
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
+#endif
mov r2, sp
sub sp, sp, #GD_SIZE /* allocate one GD above SP */
+#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
+ mov r3, sp
+ bic r3, r3, #7
+ mov sp, r3
+#else
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
+#endif
mov r9, sp /* GD is above SP */
mov r1, sp
mov r0, #0
clr_gd:
cmp r1, r2 /* while not at end of GD */
+#if defined(CONFIG_CPU_V7M)
+ itt lo
+#endif
strlo r0, [r1] /* clear 32-bit GD word */
addlo r1, r1, #4 /* move to next */
blo clr_gd
@@ -94,13 +112,22 @@ clr_gd:
*/
ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
+#if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
+ mov r3, sp
+ bic r3, r3, #7
+ mov sp, r3
+#else
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
+#endif
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
+#if defined(CONFIG_CPU_V7M)
+ orr lr, #1 /* As required by Thumb-only */
+#endif
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
here:
@@ -134,6 +161,9 @@ here:
mov r2, #0x00000000 /* prepare zero to clear BSS */
clbss_l:cmp r0, r1 /* while not at end of BSS */
+#if defined(CONFIG_CPU_V7M)
+ itt lo
+#endif
strlo r2, [r0] /* clear 32-bit BSS word */
addlo r0, r0, #4 /* move to next */
blo clbss_l
diff --git a/arch/arm/lib/interrupts_m.c b/arch/arm/lib/interrupts_m.c
new file mode 100644
index 0000000000..89ce493861
--- /dev/null
+++ b/arch/arm/lib/interrupts_m.c
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2015
+ * Kamil Lulko, <rev13@wp.pl>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+/*
+ * Upon exception entry ARMv7-M processors automatically save stack
+ * frames containing some registers. For simplicity initial
+ * implementation uses only this auto-saved stack frame.
+ * This does not contain complete register set dump,
+ * only R0-R3, R12, LR, PC and xPSR are saved.
+ */
+
+struct autosave_regs {
+ long uregs[8];
+};
+
+#define ARM_XPSR uregs[7]
+#define ARM_PC uregs[6]
+#define ARM_LR uregs[5]
+#define ARM_R12 uregs[4]
+#define ARM_R3 uregs[3]
+#define ARM_R2 uregs[2]
+#define ARM_R1 uregs[1]
+#define ARM_R0 uregs[0]
+
+int interrupt_init(void)
+{
+ return 0;
+}
+
+void enable_interrupts(void)
+{
+ return;
+}
+
+int disable_interrupts(void)
+{
+ return 0;
+}
+
+void dump_regs(struct autosave_regs *regs)
+{
+ printf("pc : %08lx lr : %08lx xPSR : %08lx\n",
+ regs->ARM_PC, regs->ARM_LR, regs->ARM_XPSR);
+ printf("r12 : %08lx r3 : %08lx r2 : %08lx\n"
+ "r1 : %08lx r0 : %08lx\n",
+ regs->ARM_R12, regs->ARM_R3, regs->ARM_R2,
+ regs->ARM_R1, regs->ARM_R0);
+}
+
+void bad_mode(void)
+{
+ panic("Resetting CPU ...\n");
+ reset_cpu(0);
+}
+
+void do_hard_fault(struct autosave_regs *autosave_regs)
+{
+ printf("Hard fault\n");
+ dump_regs(autosave_regs);
+ bad_mode();
+}
+
+void do_mm_fault(struct autosave_regs *autosave_regs)
+{
+ printf("Memory management fault\n");
+ dump_regs(autosave_regs);
+ bad_mode();
+}
+
+void do_bus_fault(struct autosave_regs *autosave_regs)
+{
+ printf("Bus fault\n");
+ dump_regs(autosave_regs);
+ bad_mode();
+}
+
+void do_usage_fault(struct autosave_regs *autosave_regs)
+{
+ printf("Usage fault\n");
+ dump_regs(autosave_regs);
+ bad_mode();
+}
+
+void do_invalid_entry(struct autosave_regs *autosave_regs)
+{
+ printf("Exception\n");
+ dump_regs(autosave_regs);
+ bad_mode();
+}
diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S
index 92f531452d..475d503dd9 100644
--- a/arch/arm/lib/relocate.S
+++ b/arch/arm/lib/relocate.S
@@ -9,6 +9,9 @@
#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>
+#ifdef CONFIG_CPU_V7M
+#include <asm/armv7m.h>
+#endif
/*
* Default/weak exception vectors relocation routine
@@ -23,6 +26,15 @@
ENTRY(relocate_vectors)
+#ifdef CONFIG_CPU_V7M
+ /*
+ * On ARMv7-M we only have to write the new vector address
+ * to VTOR register.
+ */
+ ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
+ ldr r1, =V7M_SCB_BASE
+ str r0, [r1, V7M_SCB_VTOR]
+#else
#ifdef CONFIG_HAS_VBAR
/*
* If the ARM processor has the security extensions,
@@ -47,6 +59,7 @@ ENTRY(relocate_vectors)
ldmia r0!, {r2-r8,r10}
stmia r1!, {r2-r8,r10}
#endif
+#endif
bx lr
ENDPROC(relocate_vectors)
diff --git a/arch/arm/lib/vectors_m.S b/arch/arm/lib/vectors_m.S
new file mode 100644
index 0000000000..abc7f88e00
--- /dev/null
+++ b/arch/arm/lib/vectors_m.S
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2015
+ * Kamil Lulko, <rev13@wp.pl>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/armv7m.h>
+#include <linux/linkage.h>
+
+.type __hard_fault_entry, %function
+__hard_fault_entry:
+ mov r0, sp @ pass auto-saved registers as argument
+ b do_hard_fault
+
+.type __mm_fault_entry, %function
+__mm_fault_entry:
+ mov r0, sp @ pass auto-saved registers as argument
+ b do_mm_fault
+
+.type __bus_fault_entry, %function
+__bus_fault_entry:
+ mov r0, sp @ pass auto-saved registers as argument
+ b do_bus_fault
+
+.type __usage_fault_entry, %function
+__usage_fault_entry:
+ mov r0, sp @ pass auto-saved registers as argument
+ b do_usage_fault
+
+.type __invalid_entry, %function
+__invalid_entry:
+ mov r0, sp @ pass auto-saved registers as argument
+ b do_invalid_entry
+
+ .section .vectors
+ENTRY(_start)
+ .long CONFIG_SYS_INIT_SP_ADDR @ 0 - Reset stack pointer
+ .long reset @ 1 - Reset
+ .long __invalid_entry @ 2 - NMI
+ .long __hard_fault_entry @ 3 - HardFault
+ .long __mm_fault_entry @ 4 - MemManage
+ .long __bus_fault_entry @ 5 - BusFault
+ .long __usage_fault_entry @ 6 - UsageFault
+ .long __invalid_entry @ 7 - Reserved
+ .long __invalid_entry @ 8 - Reserved
+ .long __invalid_entry @ 9 - Reserved
+ .long __invalid_entry @ 10 - Reserved
+ .long __invalid_entry @ 11 - SVCall
+ .long __invalid_entry @ 12 - Debug Monitor
+ .long __invalid_entry @ 13 - Reserved
+ .long __invalid_entry @ 14 - PendSV
+ .long __invalid_entry @ 15 - SysTick
+ .rept 255 - 16
+ .long __invalid_entry @ 16..255 - External Interrupts
+ .endr
OpenPOWER on IntegriCloud