mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
ARM: Add ARMv7-M support
Signed-off-by: Kamil Lulko <rev13@wp.pl>
This commit is contained in:
parent
5d27223ea5
commit
12d8a72913
11 changed files with 332 additions and 2 deletions
|
@ -33,6 +33,9 @@ config CPU_V7
|
|||
bool
|
||||
select HAS_VBAR
|
||||
|
||||
config CPU_V7M
|
||||
bool
|
||||
|
||||
config CPU_PXA
|
||||
bool
|
||||
|
||||
|
@ -47,6 +50,7 @@ config SYS_CPU
|
|||
default "arm1136" if CPU_ARM1136
|
||||
default "arm1176" if CPU_ARM1176
|
||||
default "armv7" if CPU_V7
|
||||
default "armv7m" if CPU_V7M
|
||||
default "pxa" if CPU_PXA
|
||||
default "sa1100" if CPU_SA1100
|
||||
default "armv8" if ARM64
|
||||
|
|
9
arch/arm/cpu/armv7m/Makefile
Normal file
9
arch/arm/cpu/armv7m/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
extra-y := start.o
|
||||
obj-y += cpu.o
|
8
arch/arm/cpu/armv7m/config.mk
Normal file
8
arch/arm/cpu/armv7m/config.mk
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# (C) Copyright 2015
|
||||
# Kamil Lulko, <rev13@wp.pl>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
PLATFORM_CPPFLAGS += -march=armv7-m -mthumb
|
35
arch/arm/cpu/armv7m/cpu.c
Normal file
35
arch/arm/cpu/armv7m/cpu.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* (C) Copyright 2010,2011
|
||||
* Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com
|
||||
*
|
||||
* (C) Copyright 2015
|
||||
* Kamil Lulko, <rev13@wp.pl>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/armv7m.h>
|
||||
|
||||
/*
|
||||
* This is called right before passing control to
|
||||
* the Linux kernel point.
|
||||
*/
|
||||
int cleanup_before_linux(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the low-level reset.
|
||||
*/
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
/*
|
||||
* Perform reset but keep priority group unchanged.
|
||||
*/
|
||||
writel((V7M_AIRCR_VECTKEY << V7M_AIRCR_VECTKEY_SHIFT)
|
||||
| (V7M_SCB->aircr & V7M_AIRCR_PRIGROUP_MSK)
|
||||
| V7M_AIRCR_SYSRESET, &V7M_SCB->aircr);
|
||||
}
|
15
arch/arm/cpu/armv7m/start.S
Normal file
15
arch/arm/cpu/armv7m/start.S
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* (C) Copyright 2015
|
||||
* Kamil Lulko, <rev13@wp.pl>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
.globl reset
|
||||
.type reset, %function
|
||||
reset:
|
||||
b _main
|
||||
|
||||
.globl c_runtime_cpu_setup
|
||||
c_runtime_cpu_setup:
|
||||
mov pc, lr
|
60
arch/arm/include/asm/armv7m.h
Normal file
60
arch/arm/include/asm/armv7m.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* (C) Copyright 2010,2011
|
||||
* Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com
|
||||
*
|
||||
* (C) Copyright 2015
|
||||
* Kamil Lulko, <rev13@wp.pl>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef ARMV7M_H
|
||||
#define ARMV7M_H
|
||||
|
||||
#if defined(__ASSEMBLY__)
|
||||
.syntax unified
|
||||
.thumb
|
||||
#endif
|
||||
|
||||
#define V7M_SCB_BASE 0xE000ED00
|
||||
#define V7M_MPU_BASE 0xE000ED90
|
||||
|
||||
#define V7M_SCB_VTOR 0x08
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
struct v7m_scb {
|
||||
uint32_t cpuid; /* CPUID Base Register */
|
||||
uint32_t icsr; /* Interrupt Control and State Register */
|
||||
uint32_t vtor; /* Vector Table Offset Register */
|
||||
uint32_t aircr; /* App Interrupt and Reset Control Register */
|
||||
};
|
||||
#define V7M_SCB ((struct v7m_scb *)V7M_SCB_BASE)
|
||||
|
||||
#define V7M_AIRCR_VECTKEY 0x5fa
|
||||
#define V7M_AIRCR_VECTKEY_SHIFT 16
|
||||
#define V7M_AIRCR_ENDIAN (1 << 15)
|
||||
#define V7M_AIRCR_PRIGROUP_SHIFT 8
|
||||
#define V7M_AIRCR_PRIGROUP_MSK (0x7 << V7M_AIRCR_PRIGROUP_SHIFT)
|
||||
#define V7M_AIRCR_SYSRESET (1 << 2)
|
||||
|
||||
#define V7M_ICSR_VECTACT_MSK 0xFF
|
||||
|
||||
struct v7m_mpu {
|
||||
uint32_t type; /* Type Register */
|
||||
uint32_t ctrl; /* Control Register */
|
||||
uint32_t rnr; /* Region Number Register */
|
||||
uint32_t rbar; /* Region Base Address Register */
|
||||
uint32_t rasr; /* Region Attribute and Size Register */
|
||||
};
|
||||
#define V7M_MPU ((struct v7m_mpu *)V7M_MPU_BASE)
|
||||
|
||||
#define V7M_MPU_CTRL_ENABLE (1 << 0)
|
||||
#define V7M_MPU_CTRL_HFNMIENA (1 << 1)
|
||||
|
||||
#define V7M_MPU_RASR_EN (1 << 0)
|
||||
#define V7M_MPU_RASR_SIZE_BITS 1
|
||||
#define V7M_MPU_RASR_SIZE_4GB (31 << V7M_MPU_RASR_SIZE_BITS)
|
||||
#define V7M_MPU_RASR_AP_RW_RW (3 << 24)
|
||||
|
||||
#endif /* !defined(__ASSEMBLY__) */
|
||||
#endif /* ARMV7M_H */
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
95
arch/arm/lib/interrupts_m.c
Normal file
95
arch/arm/lib/interrupts_m.c
Normal file
|
@ -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();
|
||||
}
|
|
@ -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,
|
||||
|
@ -46,6 +58,7 @@ ENTRY(relocate_vectors)
|
|||
stmia r1!, {r2-r8,r10}
|
||||
ldmia r0!, {r2-r8,r10}
|
||||
stmia r1!, {r2-r8,r10}
|
||||
#endif
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
|
|
57
arch/arm/lib/vectors_m.S
Normal file
57
arch/arm/lib/vectors_m.S
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue