mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-30 08:07:59 +00:00
arm64: core support
Relocation code based on a patch by Scott Wood, which is: Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: David Feng <fenghua@phytium.com.cn>
This commit is contained in:
parent
54799e4596
commit
0ae7653128
38 changed files with 1884 additions and 23 deletions
|
@ -17,7 +17,8 @@ endif
|
||||||
|
|
||||||
LDFLAGS_FINAL += --gc-sections
|
LDFLAGS_FINAL += --gc-sections
|
||||||
PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \
|
PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \
|
||||||
-fno-common -ffixed-r9 -msoft-float
|
-fno-common -ffixed-r9
|
||||||
|
PLATFORM_RELFLAGS += $(call cc-option, -msoft-float)
|
||||||
|
|
||||||
# Support generic board on ARM
|
# Support generic board on ARM
|
||||||
__HAVE_ARCH_GENERIC_BOARD := y
|
__HAVE_ARCH_GENERIC_BOARD := y
|
||||||
|
@ -105,4 +106,8 @@ PLATFORM_CPPFLAGS += $(call cc-option, -mword-relocations)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# limit ourselves to the sections we want in the .bin.
|
# limit ourselves to the sections we want in the .bin.
|
||||||
|
ifdef CONFIG_ARM64
|
||||||
|
OBJCFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rela.dyn
|
||||||
|
else
|
||||||
OBJCFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rel.dyn
|
OBJCFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rel.dyn
|
||||||
|
endif
|
||||||
|
|
17
arch/arm/cpu/armv8/Makefile
Normal file
17
arch/arm/cpu/armv8/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
# (C) Copyright 2000-2003
|
||||||
|
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
|
||||||
|
extra-y := start.o
|
||||||
|
|
||||||
|
obj-y += cpu.o
|
||||||
|
obj-y += generic_timer.o
|
||||||
|
obj-y += cache_v8.o
|
||||||
|
obj-y += exceptions.o
|
||||||
|
obj-y += cache.o
|
||||||
|
obj-y += tlb.o
|
||||||
|
obj-y += gic.o
|
||||||
|
obj-y += transition.o
|
136
arch/arm/cpu/armv8/cache.S
Normal file
136
arch/arm/cpu/armv8/cache.S
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* This file is based on sample code from ARMv8 ARM.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <version.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void __asm_flush_dcache_level(level)
|
||||||
|
*
|
||||||
|
* clean and invalidate one level cache.
|
||||||
|
*
|
||||||
|
* x0: cache level
|
||||||
|
* x1~x9: clobbered
|
||||||
|
*/
|
||||||
|
ENTRY(__asm_flush_dcache_level)
|
||||||
|
lsl x1, x0, #1
|
||||||
|
msr csselr_el1, x1 /* select cache level */
|
||||||
|
isb /* sync change of cssidr_el1 */
|
||||||
|
mrs x6, ccsidr_el1 /* read the new cssidr_el1 */
|
||||||
|
and x2, x6, #7 /* x2 <- log2(cache line size)-4 */
|
||||||
|
add x2, x2, #4 /* x2 <- log2(cache line size) */
|
||||||
|
mov x3, #0x3ff
|
||||||
|
and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */
|
||||||
|
add w4, w3, w3
|
||||||
|
sub w4, w4, 1 /* round up log2(#ways + 1) */
|
||||||
|
clz w5, w4 /* bit position of #ways */
|
||||||
|
mov x4, #0x7fff
|
||||||
|
and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */
|
||||||
|
/* x1 <- cache level << 1 */
|
||||||
|
/* x2 <- line length offset */
|
||||||
|
/* x3 <- number of cache ways - 1 */
|
||||||
|
/* x4 <- number of cache sets - 1 */
|
||||||
|
/* x5 <- bit position of #ways */
|
||||||
|
|
||||||
|
loop_set:
|
||||||
|
mov x6, x3 /* x6 <- working copy of #ways */
|
||||||
|
loop_way:
|
||||||
|
lsl x7, x6, x5
|
||||||
|
orr x9, x1, x7 /* map way and level to cisw value */
|
||||||
|
lsl x7, x4, x2
|
||||||
|
orr x9, x9, x7 /* map set number to cisw value */
|
||||||
|
dc cisw, x9 /* clean & invalidate by set/way */
|
||||||
|
subs x6, x6, #1 /* decrement the way */
|
||||||
|
b.ge loop_way
|
||||||
|
subs x4, x4, #1 /* decrement the set */
|
||||||
|
b.ge loop_set
|
||||||
|
|
||||||
|
ret
|
||||||
|
ENDPROC(__asm_flush_dcache_level)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void __asm_flush_dcache_all(void)
|
||||||
|
*
|
||||||
|
* clean and invalidate all data cache by SET/WAY.
|
||||||
|
*/
|
||||||
|
ENTRY(__asm_flush_dcache_all)
|
||||||
|
dsb sy
|
||||||
|
mrs x10, clidr_el1 /* read clidr_el1 */
|
||||||
|
lsr x11, x10, #24
|
||||||
|
and x11, x11, #0x7 /* x11 <- loc */
|
||||||
|
cbz x11, finished /* if loc is 0, exit */
|
||||||
|
mov x15, lr
|
||||||
|
mov x0, #0 /* start flush at cache level 0 */
|
||||||
|
/* x0 <- cache level */
|
||||||
|
/* x10 <- clidr_el1 */
|
||||||
|
/* x11 <- loc */
|
||||||
|
/* x15 <- return address */
|
||||||
|
|
||||||
|
loop_level:
|
||||||
|
lsl x1, x0, #1
|
||||||
|
add x1, x1, x0 /* x0 <- tripled cache level */
|
||||||
|
lsr x1, x10, x1
|
||||||
|
and x1, x1, #7 /* x1 <- cache type */
|
||||||
|
cmp x1, #2
|
||||||
|
b.lt skip /* skip if no cache or icache */
|
||||||
|
bl __asm_flush_dcache_level
|
||||||
|
skip:
|
||||||
|
add x0, x0, #1 /* increment cache level */
|
||||||
|
cmp x11, x0
|
||||||
|
b.gt loop_level
|
||||||
|
|
||||||
|
mov x0, #0
|
||||||
|
msr csselr_el1, x0 /* resotre csselr_el1 */
|
||||||
|
dsb sy
|
||||||
|
isb
|
||||||
|
mov lr, x15
|
||||||
|
|
||||||
|
finished:
|
||||||
|
ret
|
||||||
|
ENDPROC(__asm_flush_dcache_all)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void __asm_flush_dcache_range(start, end)
|
||||||
|
*
|
||||||
|
* clean & invalidate data cache in the range
|
||||||
|
*
|
||||||
|
* x0: start address
|
||||||
|
* x1: end address
|
||||||
|
*/
|
||||||
|
ENTRY(__asm_flush_dcache_range)
|
||||||
|
mrs x3, ctr_el0
|
||||||
|
lsr x3, x3, #16
|
||||||
|
and x3, x3, #0xf
|
||||||
|
mov x2, #4
|
||||||
|
lsl x2, x2, x3 /* cache line size */
|
||||||
|
|
||||||
|
/* x2 <- minimal cache line size in cache system */
|
||||||
|
sub x3, x2, #1
|
||||||
|
bic x0, x0, x3
|
||||||
|
1: dc civac, x0 /* clean & invalidate data or unified cache */
|
||||||
|
add x0, x0, x2
|
||||||
|
cmp x0, x1
|
||||||
|
b.lo 1b
|
||||||
|
dsb sy
|
||||||
|
ret
|
||||||
|
ENDPROC(__asm_flush_dcache_range)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void __asm_invalidate_icache_all(void)
|
||||||
|
*
|
||||||
|
* invalidate all tlb entries.
|
||||||
|
*/
|
||||||
|
ENTRY(__asm_invalidate_icache_all)
|
||||||
|
ic ialluis
|
||||||
|
isb sy
|
||||||
|
ret
|
||||||
|
ENDPROC(__asm_invalidate_icache_all)
|
219
arch/arm/cpu/armv8/cache_v8.c
Normal file
219
arch/arm/cpu/armv8/cache_v8.c
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
#include <asm/armv8/mmu.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||||
|
|
||||||
|
static void set_pgtable_section(u64 section, u64 memory_type)
|
||||||
|
{
|
||||||
|
u64 *page_table = (u64 *)gd->arch.tlb_addr;
|
||||||
|
u64 value;
|
||||||
|
|
||||||
|
value = (section << SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF;
|
||||||
|
value |= PMD_ATTRINDX(memory_type);
|
||||||
|
page_table[section] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* to activate the MMU we need to set up virtual memory */
|
||||||
|
static void mmu_setup(void)
|
||||||
|
{
|
||||||
|
int i, j, el;
|
||||||
|
bd_t *bd = gd->bd;
|
||||||
|
|
||||||
|
/* Setup an identity-mapping for all spaces */
|
||||||
|
for (i = 0; i < (PGTABLE_SIZE >> 3); i++)
|
||||||
|
set_pgtable_section(i, MT_DEVICE_NGNRNE);
|
||||||
|
|
||||||
|
/* Setup an identity-mapping for all RAM space */
|
||||||
|
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||||
|
ulong start = bd->bi_dram[i].start;
|
||||||
|
ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size;
|
||||||
|
for (j = start >> SECTION_SHIFT;
|
||||||
|
j < end >> SECTION_SHIFT; j++) {
|
||||||
|
set_pgtable_section(j, MT_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load TTBR0 */
|
||||||
|
el = current_el();
|
||||||
|
if (el == 1)
|
||||||
|
asm volatile("msr ttbr0_el1, %0"
|
||||||
|
: : "r" (gd->arch.tlb_addr) : "memory");
|
||||||
|
else if (el == 2)
|
||||||
|
asm volatile("msr ttbr0_el2, %0"
|
||||||
|
: : "r" (gd->arch.tlb_addr) : "memory");
|
||||||
|
else
|
||||||
|
asm volatile("msr ttbr0_el3, %0"
|
||||||
|
: : "r" (gd->arch.tlb_addr) : "memory");
|
||||||
|
|
||||||
|
/* enable the mmu */
|
||||||
|
set_sctlr(get_sctlr() | CR_M);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Performs a invalidation of the entire data cache at all levels
|
||||||
|
*/
|
||||||
|
void invalidate_dcache_all(void)
|
||||||
|
{
|
||||||
|
__asm_flush_dcache_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Performs a clean & invalidation of the entire data cache at all levels
|
||||||
|
*/
|
||||||
|
void flush_dcache_all(void)
|
||||||
|
{
|
||||||
|
__asm_flush_dcache_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invalidates range in all levels of D-cache/unified cache
|
||||||
|
*/
|
||||||
|
void invalidate_dcache_range(unsigned long start, unsigned long stop)
|
||||||
|
{
|
||||||
|
__asm_flush_dcache_range(start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush range(clean & invalidate) from all levels of D-cache/unified cache
|
||||||
|
*/
|
||||||
|
void flush_dcache_range(unsigned long start, unsigned long stop)
|
||||||
|
{
|
||||||
|
__asm_flush_dcache_range(start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dcache_enable(void)
|
||||||
|
{
|
||||||
|
/* The data cache is not active unless the mmu is enabled */
|
||||||
|
if (!(get_sctlr() & CR_M)) {
|
||||||
|
invalidate_dcache_all();
|
||||||
|
__asm_invalidate_tlb_all();
|
||||||
|
mmu_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
set_sctlr(get_sctlr() | CR_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dcache_disable(void)
|
||||||
|
{
|
||||||
|
uint32_t sctlr;
|
||||||
|
|
||||||
|
sctlr = get_sctlr();
|
||||||
|
|
||||||
|
/* if cache isn't enabled no need to disable */
|
||||||
|
if (!(sctlr & CR_C))
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_sctlr(sctlr & ~(CR_C|CR_M));
|
||||||
|
|
||||||
|
flush_dcache_all();
|
||||||
|
__asm_invalidate_tlb_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcache_status(void)
|
||||||
|
{
|
||||||
|
return (get_sctlr() & CR_C) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_SYS_DCACHE_OFF */
|
||||||
|
|
||||||
|
void invalidate_dcache_all(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_dcache_all(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate_dcache_range(unsigned long start, unsigned long stop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush_dcache_range(unsigned long start, unsigned long stop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void dcache_enable(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void dcache_disable(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcache_status(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_SYS_DCACHE_OFF */
|
||||||
|
|
||||||
|
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||||
|
|
||||||
|
void icache_enable(void)
|
||||||
|
{
|
||||||
|
set_sctlr(get_sctlr() | CR_I);
|
||||||
|
}
|
||||||
|
|
||||||
|
void icache_disable(void)
|
||||||
|
{
|
||||||
|
set_sctlr(get_sctlr() & ~CR_I);
|
||||||
|
}
|
||||||
|
|
||||||
|
int icache_status(void)
|
||||||
|
{
|
||||||
|
return (get_sctlr() & CR_I) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate_icache_all(void)
|
||||||
|
{
|
||||||
|
__asm_invalidate_icache_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_SYS_ICACHE_OFF */
|
||||||
|
|
||||||
|
void icache_enable(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void icache_disable(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int icache_status(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate_icache_all(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_SYS_ICACHE_OFF */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable dCache & iCache, whether cache is actually enabled
|
||||||
|
* depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF
|
||||||
|
*/
|
||||||
|
void enable_caches(void)
|
||||||
|
{
|
||||||
|
icache_enable();
|
||||||
|
dcache_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush range from all levels of d-cache/unified-cache
|
||||||
|
*/
|
||||||
|
void flush_cache(unsigned long start, unsigned long size)
|
||||||
|
{
|
||||||
|
flush_dcache_range(start, start + size);
|
||||||
|
}
|
15
arch/arm/cpu/armv8/config.mk
Normal file
15
arch/arm/cpu/armv8/config.mk
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#
|
||||||
|
# (C) Copyright 2002
|
||||||
|
# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
PLATFORM_RELFLAGS += -fno-common -ffixed-x18
|
||||||
|
|
||||||
|
# SEE README.arm-unaligned-accesses
|
||||||
|
PF_NO_UNALIGNED := $(call cc-option, -mstrict-align)
|
||||||
|
PLATFORM_NO_UNALIGNED := $(PF_NO_UNALIGNED)
|
||||||
|
|
||||||
|
PF_CPPFLAGS_ARMV8 := $(call cc-option, -march=armv8-a)
|
||||||
|
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV8)
|
||||||
|
PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)
|
43
arch/arm/cpu/armv8/cpu.c
Normal file
43
arch/arm/cpu/armv8/cpu.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2008 Texas Insturments
|
||||||
|
*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||||
|
* Marius Groeger <mgroeger@sysgo.de>
|
||||||
|
*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
|
int cleanup_before_linux(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* this function is called just before we call linux
|
||||||
|
* it prepares the processor for linux
|
||||||
|
*
|
||||||
|
* disable interrupt and turn off caches etc ...
|
||||||
|
*/
|
||||||
|
disable_interrupts();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn off I-cache and invalidate it
|
||||||
|
*/
|
||||||
|
icache_disable();
|
||||||
|
invalidate_icache_all();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* turn off D-cache
|
||||||
|
* dcache_disable() in turn flushes the d-cache and disables MMU
|
||||||
|
*/
|
||||||
|
dcache_disable();
|
||||||
|
invalidate_dcache_all();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
113
arch/arm/cpu/armv8/exceptions.S
Normal file
113
arch/arm/cpu/armv8/exceptions.S
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <version.h>
|
||||||
|
#include <asm/ptrace.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enter Exception.
|
||||||
|
* This will save the processor state that is ELR/X0~X30
|
||||||
|
* to the stack frame.
|
||||||
|
*/
|
||||||
|
.macro exception_entry
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
stp x27, x28, [sp, #-16]!
|
||||||
|
stp x25, x26, [sp, #-16]!
|
||||||
|
stp x23, x24, [sp, #-16]!
|
||||||
|
stp x21, x22, [sp, #-16]!
|
||||||
|
stp x19, x20, [sp, #-16]!
|
||||||
|
stp x17, x18, [sp, #-16]!
|
||||||
|
stp x15, x16, [sp, #-16]!
|
||||||
|
stp x13, x14, [sp, #-16]!
|
||||||
|
stp x11, x12, [sp, #-16]!
|
||||||
|
stp x9, x10, [sp, #-16]!
|
||||||
|
stp x7, x8, [sp, #-16]!
|
||||||
|
stp x5, x6, [sp, #-16]!
|
||||||
|
stp x3, x4, [sp, #-16]!
|
||||||
|
stp x1, x2, [sp, #-16]!
|
||||||
|
|
||||||
|
/* Could be running at EL3/EL2/EL1 */
|
||||||
|
switch_el x11, 3f, 2f, 1f
|
||||||
|
3: mrs x1, esr_el3
|
||||||
|
mrs x2, elr_el3
|
||||||
|
b 0f
|
||||||
|
2: mrs x1, esr_el2
|
||||||
|
mrs x2, elr_el2
|
||||||
|
b 0f
|
||||||
|
1: mrs x1, esr_el1
|
||||||
|
mrs x2, elr_el1
|
||||||
|
0:
|
||||||
|
stp x2, x0, [sp, #-16]!
|
||||||
|
mov x0, sp
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception vectors.
|
||||||
|
*/
|
||||||
|
.align 11
|
||||||
|
.globl vectors
|
||||||
|
vectors:
|
||||||
|
.align 7
|
||||||
|
b _do_bad_sync /* Current EL Synchronous Thread */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_bad_irq /* Current EL IRQ Thread */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_bad_fiq /* Current EL FIQ Thread */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_bad_error /* Current EL Error Thread */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_sync /* Current EL Synchronous Handler */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_irq /* Current EL IRQ Handler */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_fiq /* Current EL FIQ Handler */
|
||||||
|
|
||||||
|
.align 7
|
||||||
|
b _do_error /* Current EL Error Handler */
|
||||||
|
|
||||||
|
|
||||||
|
_do_bad_sync:
|
||||||
|
exception_entry
|
||||||
|
bl do_bad_sync
|
||||||
|
|
||||||
|
_do_bad_irq:
|
||||||
|
exception_entry
|
||||||
|
bl do_bad_irq
|
||||||
|
|
||||||
|
_do_bad_fiq:
|
||||||
|
exception_entry
|
||||||
|
bl do_bad_fiq
|
||||||
|
|
||||||
|
_do_bad_error:
|
||||||
|
exception_entry
|
||||||
|
bl do_bad_error
|
||||||
|
|
||||||
|
_do_sync:
|
||||||
|
exception_entry
|
||||||
|
bl do_sync
|
||||||
|
|
||||||
|
_do_irq:
|
||||||
|
exception_entry
|
||||||
|
bl do_irq
|
||||||
|
|
||||||
|
_do_fiq:
|
||||||
|
exception_entry
|
||||||
|
bl do_fiq
|
||||||
|
|
||||||
|
_do_error:
|
||||||
|
exception_entry
|
||||||
|
bl do_error
|
31
arch/arm/cpu/armv8/generic_timer.c
Normal file
31
arch/arm/cpu/armv8/generic_timer.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic timer implementation of get_tbclk()
|
||||||
|
*/
|
||||||
|
unsigned long get_tbclk(void)
|
||||||
|
{
|
||||||
|
unsigned long cntfrq;
|
||||||
|
asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
|
||||||
|
return cntfrq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic timer implementation of timer_read_counter()
|
||||||
|
*/
|
||||||
|
unsigned long timer_read_counter(void)
|
||||||
|
{
|
||||||
|
unsigned long cntpct;
|
||||||
|
isb();
|
||||||
|
asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct));
|
||||||
|
return cntpct;
|
||||||
|
}
|
106
arch/arm/cpu/armv8/gic.S
Normal file
106
arch/arm/cpu/armv8/gic.S
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* GIC Initialization Routines.
|
||||||
|
*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
#include <asm/gic.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* void gic_init(void) __attribute__((weak));
|
||||||
|
*
|
||||||
|
* Currently, this routine only initialize secure copy of GIC
|
||||||
|
* with Security Extensions at EL3.
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
WEAK(gic_init)
|
||||||
|
branch_if_slave x0, 2f
|
||||||
|
|
||||||
|
/* Initialize Distributor and SPIs */
|
||||||
|
ldr x1, =GICD_BASE
|
||||||
|
mov w0, #0x3 /* EnableGrp0 | EnableGrp1 */
|
||||||
|
str w0, [x1, GICD_CTLR] /* Secure GICD_CTLR */
|
||||||
|
ldr w0, [x1, GICD_TYPER]
|
||||||
|
and w2, w0, #0x1f /* ITLinesNumber */
|
||||||
|
cbz w2, 2f /* No SPIs */
|
||||||
|
add x1, x1, (GICD_IGROUPRn + 4)
|
||||||
|
mov w0, #~0 /* Config SPIs as Grp1 */
|
||||||
|
1: str w0, [x1], #0x4
|
||||||
|
sub w2, w2, #0x1
|
||||||
|
cbnz w2, 1b
|
||||||
|
|
||||||
|
/* Initialize SGIs and PPIs */
|
||||||
|
2: ldr x1, =GICD_BASE
|
||||||
|
mov w0, #~0 /* Config SGIs and PPIs as Grp1 */
|
||||||
|
str w0, [x1, GICD_IGROUPRn] /* GICD_IGROUPR0 */
|
||||||
|
mov w0, #0x1 /* Enable SGI 0 */
|
||||||
|
str w0, [x1, GICD_ISENABLERn]
|
||||||
|
|
||||||
|
/* Initialize Cpu Interface */
|
||||||
|
ldr x1, =GICC_BASE
|
||||||
|
mov w0, #0x1e7 /* Disable IRQ/FIQ Bypass & */
|
||||||
|
/* Enable Ack Group1 Interrupt & */
|
||||||
|
/* EnableGrp0 & EnableGrp1 */
|
||||||
|
str w0, [x1, GICC_CTLR] /* Secure GICC_CTLR */
|
||||||
|
|
||||||
|
mov w0, #0x1 << 7 /* Non-Secure access to GICC_PMR */
|
||||||
|
str w0, [x1, GICC_PMR]
|
||||||
|
|
||||||
|
ret
|
||||||
|
ENDPROC(gic_init)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* void gic_send_sgi(u64 sgi) __attribute__((weak));
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
WEAK(gic_send_sgi)
|
||||||
|
ldr x1, =GICD_BASE
|
||||||
|
mov w2, #0x8000
|
||||||
|
movk w2, #0x100, lsl #16
|
||||||
|
orr w2, w2, w0
|
||||||
|
str w2, [x1, GICD_SGIR]
|
||||||
|
ret
|
||||||
|
ENDPROC(gic_send_sgi)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* void wait_for_wakeup(void) __attribute__((weak));
|
||||||
|
*
|
||||||
|
* Wait for SGI 0 from master.
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
WEAK(wait_for_wakeup)
|
||||||
|
ldr x1, =GICC_BASE
|
||||||
|
0: wfi
|
||||||
|
ldr w0, [x1, GICC_AIAR]
|
||||||
|
str w0, [x1, GICC_AEOIR]
|
||||||
|
cbnz w0, 0b
|
||||||
|
ret
|
||||||
|
ENDPROC(wait_for_wakeup)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* void smp_kick_all_cpus(void) __attribute__((weak));
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
WEAK(smp_kick_all_cpus)
|
||||||
|
/* Kick secondary cpus up by SGI 0 interrupt */
|
||||||
|
mov x0, xzr /* SGI 0 */
|
||||||
|
mov x29, lr /* Save LR */
|
||||||
|
bl gic_send_sgi
|
||||||
|
mov lr, x29 /* Restore LR */
|
||||||
|
ret
|
||||||
|
ENDPROC(smp_kick_all_cpus)
|
164
arch/arm/cpu/armv8/start.S
Normal file
164
arch/arm/cpu/armv8/start.S
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <version.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
#include <asm/armv8/mmu.h>
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
*
|
||||||
|
* Startup Code (reset vector)
|
||||||
|
*
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
b reset
|
||||||
|
|
||||||
|
.align 3
|
||||||
|
|
||||||
|
.globl _TEXT_BASE
|
||||||
|
_TEXT_BASE:
|
||||||
|
.quad CONFIG_SYS_TEXT_BASE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are defined in the linker script.
|
||||||
|
*/
|
||||||
|
.globl _end_ofs
|
||||||
|
_end_ofs:
|
||||||
|
.quad _end - _start
|
||||||
|
|
||||||
|
.globl _bss_start_ofs
|
||||||
|
_bss_start_ofs:
|
||||||
|
.quad __bss_start - _start
|
||||||
|
|
||||||
|
.globl _bss_end_ofs
|
||||||
|
_bss_end_ofs:
|
||||||
|
.quad __bss_end - _start
|
||||||
|
|
||||||
|
reset:
|
||||||
|
/*
|
||||||
|
* Could be EL3/EL2/EL1, Initial State:
|
||||||
|
* Little Endian, MMU Disabled, i/dCache Disabled
|
||||||
|
*/
|
||||||
|
adr x0, vectors
|
||||||
|
switch_el x1, 3f, 2f, 1f
|
||||||
|
3: msr vbar_el3, x0
|
||||||
|
msr cptr_el3, xzr /* Enable FP/SIMD */
|
||||||
|
ldr x0, =COUNTER_FREQUENCY
|
||||||
|
msr cntfrq_el0, x0 /* Initialize CNTFRQ */
|
||||||
|
b 0f
|
||||||
|
2: msr vbar_el2, x0
|
||||||
|
mov x0, #0x33ff
|
||||||
|
msr cptr_el2, x0 /* Enable FP/SIMD */
|
||||||
|
b 0f
|
||||||
|
1: msr vbar_el1, x0
|
||||||
|
mov x0, #3 << 20
|
||||||
|
msr cpacr_el1, x0 /* Enable FP/SIMD */
|
||||||
|
0:
|
||||||
|
|
||||||
|
/* Cache/BPB/TLB Invalidate */
|
||||||
|
bl __asm_flush_dcache_all /* dCache clean&invalidate */
|
||||||
|
bl __asm_invalidate_icache_all /* iCache invalidate */
|
||||||
|
bl __asm_invalidate_tlb_all /* invalidate TLBs */
|
||||||
|
|
||||||
|
/* Processor specific initialization */
|
||||||
|
bl lowlevel_init
|
||||||
|
|
||||||
|
branch_if_master x0, x1, master_cpu
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slave CPUs
|
||||||
|
*/
|
||||||
|
slave_cpu:
|
||||||
|
wfe
|
||||||
|
ldr x1, =CPU_RELEASE_ADDR
|
||||||
|
ldr x0, [x1]
|
||||||
|
cbz x0, slave_cpu
|
||||||
|
br x0 /* branch to the given address */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Master CPU
|
||||||
|
*/
|
||||||
|
master_cpu:
|
||||||
|
bl _main
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
WEAK(lowlevel_init)
|
||||||
|
/* Initialize GIC Secure Bank Status */
|
||||||
|
mov x29, lr /* Save LR */
|
||||||
|
bl gic_init
|
||||||
|
|
||||||
|
branch_if_master x0, x1, 1f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slave should wait for master clearing spin table.
|
||||||
|
* This sync prevent salves observing incorrect
|
||||||
|
* value of spin table and jumping to wrong place.
|
||||||
|
*/
|
||||||
|
bl wait_for_wakeup
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All processors will enter EL2 and optionally EL1.
|
||||||
|
*/
|
||||||
|
bl armv8_switch_to_el2
|
||||||
|
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
|
||||||
|
bl armv8_switch_to_el1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
1:
|
||||||
|
mov lr, x29 /* Restore LR */
|
||||||
|
ret
|
||||||
|
ENDPROC(lowlevel_init)
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
ENTRY(c_runtime_cpu_setup)
|
||||||
|
/* If I-cache is enabled invalidate it */
|
||||||
|
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||||
|
ic iallu /* I+BTB cache invalidate */
|
||||||
|
isb sy
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||||
|
/*
|
||||||
|
* Setup MAIR and TCR.
|
||||||
|
*/
|
||||||
|
ldr x0, =MEMORY_ATTRIBUTES
|
||||||
|
ldr x1, =TCR_FLAGS
|
||||||
|
|
||||||
|
switch_el x2, 3f, 2f, 1f
|
||||||
|
3: orr x1, x1, TCR_EL3_IPS_BITS
|
||||||
|
msr mair_el3, x0
|
||||||
|
msr tcr_el3, x1
|
||||||
|
b 0f
|
||||||
|
2: orr x1, x1, TCR_EL2_IPS_BITS
|
||||||
|
msr mair_el2, x0
|
||||||
|
msr tcr_el2, x1
|
||||||
|
b 0f
|
||||||
|
1: orr x1, x1, TCR_EL1_IPS_BITS
|
||||||
|
msr mair_el1, x0
|
||||||
|
msr tcr_el1, x1
|
||||||
|
0:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Relocate vBAR */
|
||||||
|
adr x0, vectors
|
||||||
|
switch_el x1, 3f, 2f, 1f
|
||||||
|
3: msr vbar_el3, x0
|
||||||
|
b 0f
|
||||||
|
2: msr vbar_el2, x0
|
||||||
|
b 0f
|
||||||
|
1: msr vbar_el1, x0
|
||||||
|
0:
|
||||||
|
|
||||||
|
ret
|
||||||
|
ENDPROC(c_runtime_cpu_setup)
|
34
arch/arm/cpu/armv8/tlb.S
Normal file
34
arch/arm/cpu/armv8/tlb.S
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <version.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void __asm_invalidate_tlb_all(void)
|
||||||
|
*
|
||||||
|
* invalidate all tlb entries.
|
||||||
|
*/
|
||||||
|
ENTRY(__asm_invalidate_tlb_all)
|
||||||
|
switch_el x9, 3f, 2f, 1f
|
||||||
|
3: tlbi alle3
|
||||||
|
dsb sy
|
||||||
|
isb
|
||||||
|
b 0f
|
||||||
|
2: tlbi alle2
|
||||||
|
dsb sy
|
||||||
|
isb
|
||||||
|
b 0f
|
||||||
|
1: tlbi vmalle1
|
||||||
|
dsb sy
|
||||||
|
isb
|
||||||
|
0:
|
||||||
|
ret
|
||||||
|
ENDPROC(__asm_invalidate_tlb_all)
|
83
arch/arm/cpu/armv8/transition.S
Normal file
83
arch/arm/cpu/armv8/transition.S
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <version.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
|
||||||
|
ENTRY(armv8_switch_to_el2)
|
||||||
|
switch_el x0, 1f, 0f, 0f
|
||||||
|
0: ret
|
||||||
|
1:
|
||||||
|
mov x0, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */
|
||||||
|
msr scr_el3, x0
|
||||||
|
msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */
|
||||||
|
mov x0, #0x33ff
|
||||||
|
msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */
|
||||||
|
|
||||||
|
/* Initialize SCTLR_EL2 */
|
||||||
|
msr sctlr_el2, xzr
|
||||||
|
|
||||||
|
/* Return to the EL2_SP2 mode from EL3 */
|
||||||
|
mov x0, sp
|
||||||
|
msr sp_el2, x0 /* Migrate SP */
|
||||||
|
mrs x0, vbar_el3
|
||||||
|
msr vbar_el2, x0 /* Migrate VBAR */
|
||||||
|
mov x0, #0x3c9
|
||||||
|
msr spsr_el3, x0 /* EL2_SP2 | D | A | I | F */
|
||||||
|
msr elr_el3, lr
|
||||||
|
eret
|
||||||
|
ENDPROC(armv8_switch_to_el2)
|
||||||
|
|
||||||
|
ENTRY(armv8_switch_to_el1)
|
||||||
|
switch_el x0, 0f, 1f, 0f
|
||||||
|
0: ret
|
||||||
|
1:
|
||||||
|
/* Initialize Generic Timers */
|
||||||
|
mrs x0, cnthctl_el2
|
||||||
|
orr x0, x0, #0x3 /* Enable EL1 access to timers */
|
||||||
|
msr cnthctl_el2, x0
|
||||||
|
msr cntvoff_el2, x0
|
||||||
|
mrs x0, cntkctl_el1
|
||||||
|
orr x0, x0, #0x3 /* Enable EL0 access to timers */
|
||||||
|
msr cntkctl_el1, x0
|
||||||
|
|
||||||
|
/* Initilize MPID/MPIDR registers */
|
||||||
|
mrs x0, midr_el1
|
||||||
|
mrs x1, mpidr_el1
|
||||||
|
msr vpidr_el2, x0
|
||||||
|
msr vmpidr_el2, x1
|
||||||
|
|
||||||
|
/* Disable coprocessor traps */
|
||||||
|
mov x0, #0x33ff
|
||||||
|
msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */
|
||||||
|
msr hstr_el2, xzr /* Disable coprocessor traps to EL2 */
|
||||||
|
mov x0, #3 << 20
|
||||||
|
msr cpacr_el1, x0 /* Enable FP/SIMD at EL1 */
|
||||||
|
|
||||||
|
/* Initialize HCR_EL2 */
|
||||||
|
mov x0, #(1 << 31) /* 64bit EL1 */
|
||||||
|
orr x0, x0, #(1 << 29) /* Disable HVC */
|
||||||
|
msr hcr_el2, x0
|
||||||
|
|
||||||
|
/* SCTLR_EL1 initialization */
|
||||||
|
mov x0, #0x0800
|
||||||
|
movk x0, #0x30d0, lsl #16
|
||||||
|
msr sctlr_el1, x0
|
||||||
|
|
||||||
|
/* Return to the EL1_SP1 mode from EL2 */
|
||||||
|
mov x0, sp
|
||||||
|
msr sp_el1, x0 /* Migrate SP */
|
||||||
|
mrs x0, vbar_el2
|
||||||
|
msr vbar_el1, x0 /* Migrate VBAR */
|
||||||
|
mov x0, #0x3c5
|
||||||
|
msr spsr_el2, x0 /* EL1_SP1 | D | A | I | F */
|
||||||
|
msr elr_el2, lr
|
||||||
|
eret
|
||||||
|
ENDPROC(armv8_switch_to_el1)
|
89
arch/arm/cpu/armv8/u-boot.lds
Normal file
89
arch/arm/cpu/armv8/u-boot.lds
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* (C) Copyright 2002
|
||||||
|
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
|
||||||
|
OUTPUT_ARCH(aarch64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x00000000;
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.__image_copy_start)
|
||||||
|
CPUDIR/start.o (.text*)
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
.data : {
|
||||||
|
*(.data*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
. = .;
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
.u_boot_list : {
|
||||||
|
KEEP(*(SORT(.u_boot_list*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
.image_copy_end :
|
||||||
|
{
|
||||||
|
*(.__image_copy_end)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
.rel_dyn_start :
|
||||||
|
{
|
||||||
|
*(.__rel_dyn_start)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rela.dyn : {
|
||||||
|
*(.rela*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rel_dyn_end :
|
||||||
|
{
|
||||||
|
*(.__rel_dyn_end)
|
||||||
|
}
|
||||||
|
|
||||||
|
_end = .;
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
.bss_start : {
|
||||||
|
KEEP(*(.__bss_start));
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss*)
|
||||||
|
. = ALIGN(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss_end : {
|
||||||
|
KEEP(*(.__bss_end));
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ : { *(.dynsym) }
|
||||||
|
/DISCARD/ : { *(.dynstr*) }
|
||||||
|
/DISCARD/ : { *(.dynamic*) }
|
||||||
|
/DISCARD/ : { *(.plt*) }
|
||||||
|
/DISCARD/ : { *(.interp*) }
|
||||||
|
/DISCARD/ : { *(.gnu*) }
|
||||||
|
}
|
111
arch/arm/include/asm/armv8/mmu.h
Normal file
111
arch/arm/include/asm/armv8/mmu.h
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_ARMV8_MMU_H_
|
||||||
|
#define _ASM_ARMV8_MMU_H_
|
||||||
|
|
||||||
|
#ifdef __ASSEMBLY__
|
||||||
|
#define _AC(X, Y) X
|
||||||
|
#else
|
||||||
|
#define _AC(X, Y) (X##Y)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UL(x) _AC(x, UL)
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/*
|
||||||
|
* The following definitions are related each other, shoud be
|
||||||
|
* calculated specifically.
|
||||||
|
*/
|
||||||
|
#define VA_BITS (42) /* 42 bits virtual address */
|
||||||
|
|
||||||
|
/* PAGE_SHIFT determines the page size */
|
||||||
|
#undef PAGE_SIZE
|
||||||
|
#define PAGE_SHIFT 16
|
||||||
|
#define PAGE_SIZE (1 << PAGE_SHIFT)
|
||||||
|
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* section address mask and size definitions.
|
||||||
|
*/
|
||||||
|
#define SECTION_SHIFT 29
|
||||||
|
#define SECTION_SIZE (UL(1) << SECTION_SHIFT)
|
||||||
|
#define SECTION_MASK (~(SECTION_SIZE-1))
|
||||||
|
/***************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory types
|
||||||
|
*/
|
||||||
|
#define MT_DEVICE_NGNRNE 0
|
||||||
|
#define MT_DEVICE_NGNRE 1
|
||||||
|
#define MT_DEVICE_GRE 2
|
||||||
|
#define MT_NORMAL_NC 3
|
||||||
|
#define MT_NORMAL 4
|
||||||
|
|
||||||
|
#define MEMORY_ATTRIBUTES ((0x00 << (MT_DEVICE_NGNRNE*8)) | \
|
||||||
|
(0x04 << (MT_DEVICE_NGNRE*8)) | \
|
||||||
|
(0x0c << (MT_DEVICE_GRE*8)) | \
|
||||||
|
(0x44 << (MT_NORMAL_NC*8)) | \
|
||||||
|
(UL(0xff) << (MT_NORMAL*8)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hardware page table definitions.
|
||||||
|
*
|
||||||
|
* Level 2 descriptor (PMD).
|
||||||
|
*/
|
||||||
|
#define PMD_TYPE_MASK (3 << 0)
|
||||||
|
#define PMD_TYPE_FAULT (0 << 0)
|
||||||
|
#define PMD_TYPE_TABLE (3 << 0)
|
||||||
|
#define PMD_TYPE_SECT (1 << 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Section
|
||||||
|
*/
|
||||||
|
#define PMD_SECT_S (3 << 8)
|
||||||
|
#define PMD_SECT_AF (1 << 10)
|
||||||
|
#define PMD_SECT_NG (1 << 11)
|
||||||
|
#define PMD_SECT_PXN (UL(1) << 53)
|
||||||
|
#define PMD_SECT_UXN (UL(1) << 54)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AttrIndx[2:0]
|
||||||
|
*/
|
||||||
|
#define PMD_ATTRINDX(t) ((t) << 2)
|
||||||
|
#define PMD_ATTRINDX_MASK (7 << 2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCR flags.
|
||||||
|
*/
|
||||||
|
#define TCR_T0SZ(x) ((64 - (x)) << 0)
|
||||||
|
#define TCR_IRGN_NC (0 << 8)
|
||||||
|
#define TCR_IRGN_WBWA (1 << 8)
|
||||||
|
#define TCR_IRGN_WT (2 << 8)
|
||||||
|
#define TCR_IRGN_WBNWA (3 << 8)
|
||||||
|
#define TCR_IRGN_MASK (3 << 8)
|
||||||
|
#define TCR_ORGN_NC (0 << 10)
|
||||||
|
#define TCR_ORGN_WBWA (1 << 10)
|
||||||
|
#define TCR_ORGN_WT (2 << 10)
|
||||||
|
#define TCR_ORGN_WBNWA (3 << 10)
|
||||||
|
#define TCR_ORGN_MASK (3 << 10)
|
||||||
|
#define TCR_SHARED_NON (0 << 12)
|
||||||
|
#define TCR_SHARED_OUTER (1 << 12)
|
||||||
|
#define TCR_SHARED_INNER (2 << 12)
|
||||||
|
#define TCR_TG0_4K (0 << 14)
|
||||||
|
#define TCR_TG0_64K (1 << 14)
|
||||||
|
#define TCR_TG0_16K (2 << 14)
|
||||||
|
#define TCR_EL1_IPS_BITS (UL(3) << 32) /* 42 bits physical address */
|
||||||
|
#define TCR_EL2_IPS_BITS (3 << 16) /* 42 bits physical address */
|
||||||
|
#define TCR_EL3_IPS_BITS (3 << 16) /* 42 bits physical address */
|
||||||
|
|
||||||
|
/* PTWs cacheable, inner/outer WBWA and non-shareable */
|
||||||
|
#define TCR_FLAGS (TCR_TG0_64K | \
|
||||||
|
TCR_SHARED_NON | \
|
||||||
|
TCR_ORGN_WBWA | \
|
||||||
|
TCR_IRGN_WBWA | \
|
||||||
|
TCR_T0SZ(VA_BITS))
|
||||||
|
|
||||||
|
#endif /* _ASM_ARMV8_MMU_H_ */
|
|
@ -23,10 +23,22 @@
|
||||||
# define __SWAB_64_THRU_32__
|
# define __SWAB_64_THRU_32__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
|
||||||
|
#ifdef __AARCH64EB__
|
||||||
|
#include <linux/byteorder/big_endian.h>
|
||||||
|
#else
|
||||||
|
#include <linux/byteorder/little_endian.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#ifdef __ARMEB__
|
#ifdef __ARMEB__
|
||||||
#include <linux/byteorder/big_endian.h>
|
#include <linux/byteorder/big_endian.h>
|
||||||
#else
|
#else
|
||||||
#include <linux/byteorder/little_endian.h>
|
#include <linux/byteorder/little_endian.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARM64
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalidate L2 Cache using co-proc instruction
|
* Invalidate L2 Cache using co-proc instruction
|
||||||
*/
|
*/
|
||||||
|
@ -28,6 +30,9 @@ void l2_cache_disable(void);
|
||||||
void set_section_dcache(int section, enum dcache_option option);
|
void set_section_dcache(int section, enum dcache_option option);
|
||||||
|
|
||||||
void dram_bank_mmu_setup(int bank);
|
void dram_bank_mmu_setup(int bank);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The current upper bound for ARM L1 data cache line sizes is 64 bytes. We
|
* The current upper bound for ARM L1 data cache line sizes is 64 bytes. We
|
||||||
* use that value for aligning DMA buffers unless the board config has specified
|
* use that value for aligning DMA buffers unless the board config has specified
|
||||||
|
|
|
@ -9,4 +9,10 @@
|
||||||
|
|
||||||
#define CONFIG_LMB
|
#define CONFIG_LMB
|
||||||
#define CONFIG_SYS_BOOT_RAMDISK_HIGH
|
#define CONFIG_SYS_BOOT_RAMDISK_HIGH
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
#define CONFIG_PHYS_64BIT
|
||||||
|
#define CONFIG_STATIC_RELA
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,19 +1,54 @@
|
||||||
#ifndef __GIC_V2_H__
|
#ifndef __GIC_H__
|
||||||
#define __GIC_V2_H__
|
#define __GIC_H__
|
||||||
|
|
||||||
/* register offsets for the ARM generic interrupt controller (GIC) */
|
/* Register offsets for the ARM generic interrupt controller (GIC) */
|
||||||
|
|
||||||
#define GIC_DIST_OFFSET 0x1000
|
#define GIC_DIST_OFFSET 0x1000
|
||||||
#define GICD_CTLR 0x0000
|
|
||||||
#define GICD_TYPER 0x0004
|
|
||||||
#define GICD_IGROUPRn 0x0080
|
|
||||||
#define GICD_SGIR 0x0F00
|
|
||||||
|
|
||||||
#define GIC_CPU_OFFSET_A9 0x0100
|
#define GIC_CPU_OFFSET_A9 0x0100
|
||||||
#define GIC_CPU_OFFSET_A15 0x2000
|
#define GIC_CPU_OFFSET_A15 0x2000
|
||||||
|
|
||||||
|
/* Distributor Registers */
|
||||||
|
#define GICD_CTLR 0x0000
|
||||||
|
#define GICD_TYPER 0x0004
|
||||||
|
#define GICD_IIDR 0x0008
|
||||||
|
#define GICD_STATUSR 0x0010
|
||||||
|
#define GICD_SETSPI_NSR 0x0040
|
||||||
|
#define GICD_CLRSPI_NSR 0x0048
|
||||||
|
#define GICD_SETSPI_SR 0x0050
|
||||||
|
#define GICD_CLRSPI_SR 0x0058
|
||||||
|
#define GICD_SEIR 0x0068
|
||||||
|
#define GICD_IGROUPRn 0x0080
|
||||||
|
#define GICD_ISENABLERn 0x0100
|
||||||
|
#define GICD_ICENABLERn 0x0180
|
||||||
|
#define GICD_ISPENDRn 0x0200
|
||||||
|
#define GICD_ICPENDRn 0x0280
|
||||||
|
#define GICD_ISACTIVERn 0x0300
|
||||||
|
#define GICD_ICACTIVERn 0x0380
|
||||||
|
#define GICD_IPRIORITYRn 0x0400
|
||||||
|
#define GICD_ITARGETSRn 0x0800
|
||||||
|
#define GICD_ICFGR 0x0c00
|
||||||
|
#define GICD_IGROUPMODRn 0x0d00
|
||||||
|
#define GICD_NSACRn 0x0e00
|
||||||
|
#define GICD_SGIR 0x0f00
|
||||||
|
#define GICD_CPENDSGIRn 0x0f10
|
||||||
|
#define GICD_SPENDSGIRn 0x0f20
|
||||||
|
#define GICD_IROUTERn 0x6000
|
||||||
|
|
||||||
|
/* Cpu Interface Memory Mapped Registers */
|
||||||
#define GICC_CTLR 0x0000
|
#define GICC_CTLR 0x0000
|
||||||
#define GICC_PMR 0x0004
|
#define GICC_PMR 0x0004
|
||||||
|
#define GICC_BPR 0x0008
|
||||||
#define GICC_IAR 0x000C
|
#define GICC_IAR 0x000C
|
||||||
#define GICC_EOIR 0x0010
|
#define GICC_EOIR 0x0010
|
||||||
|
#define GICC_RPR 0x0014
|
||||||
|
#define GICC_HPPIR 0x0018
|
||||||
|
#define GICC_ABPR 0x001c
|
||||||
|
#define GICC_AIAR 0x0020
|
||||||
|
#define GICC_AEOIR 0x0024
|
||||||
|
#define GICC_AHPPIR 0x0028
|
||||||
|
#define GICC_APRn 0x00d0
|
||||||
|
#define GICC_NSAPRn 0x00e0
|
||||||
|
#define GICC_IIDR 0x00fc
|
||||||
|
#define GICC_DIR 0x1000
|
||||||
|
|
||||||
#endif
|
#endif /* __GIC_H__ */
|
||||||
|
|
|
@ -47,6 +47,10 @@ struct arch_global_data {
|
||||||
|
|
||||||
#include <asm-generic/global_data.h>
|
#include <asm-generic/global_data.h>
|
||||||
|
|
||||||
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")
|
#ifdef CONFIG_ARM64
|
||||||
|
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("x18")
|
||||||
|
#else
|
||||||
|
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __ASM_GBL_DATA_H */
|
#endif /* __ASM_GBL_DATA_H */
|
||||||
|
|
|
@ -75,42 +75,45 @@ static inline phys_addr_t virt_to_phys(void * vaddr)
|
||||||
#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
|
#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
|
||||||
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
|
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
|
||||||
|
|
||||||
extern inline void __raw_writesb(unsigned int addr, const void *data, int bytelen)
|
extern inline void __raw_writesb(unsigned long addr, const void *data,
|
||||||
|
int bytelen)
|
||||||
{
|
{
|
||||||
uint8_t *buf = (uint8_t *)data;
|
uint8_t *buf = (uint8_t *)data;
|
||||||
while(bytelen--)
|
while(bytelen--)
|
||||||
__arch_putb(*buf++, addr);
|
__arch_putb(*buf++, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern inline void __raw_writesw(unsigned int addr, const void *data, int wordlen)
|
extern inline void __raw_writesw(unsigned long addr, const void *data,
|
||||||
|
int wordlen)
|
||||||
{
|
{
|
||||||
uint16_t *buf = (uint16_t *)data;
|
uint16_t *buf = (uint16_t *)data;
|
||||||
while(wordlen--)
|
while(wordlen--)
|
||||||
__arch_putw(*buf++, addr);
|
__arch_putw(*buf++, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern inline void __raw_writesl(unsigned int addr, const void *data, int longlen)
|
extern inline void __raw_writesl(unsigned long addr, const void *data,
|
||||||
|
int longlen)
|
||||||
{
|
{
|
||||||
uint32_t *buf = (uint32_t *)data;
|
uint32_t *buf = (uint32_t *)data;
|
||||||
while(longlen--)
|
while(longlen--)
|
||||||
__arch_putl(*buf++, addr);
|
__arch_putl(*buf++, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern inline void __raw_readsb(unsigned int addr, void *data, int bytelen)
|
extern inline void __raw_readsb(unsigned long addr, void *data, int bytelen)
|
||||||
{
|
{
|
||||||
uint8_t *buf = (uint8_t *)data;
|
uint8_t *buf = (uint8_t *)data;
|
||||||
while(bytelen--)
|
while(bytelen--)
|
||||||
*buf++ = __arch_getb(addr);
|
*buf++ = __arch_getb(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern inline void __raw_readsw(unsigned int addr, void *data, int wordlen)
|
extern inline void __raw_readsw(unsigned long addr, void *data, int wordlen)
|
||||||
{
|
{
|
||||||
uint16_t *buf = (uint16_t *)data;
|
uint16_t *buf = (uint16_t *)data;
|
||||||
while(wordlen--)
|
while(wordlen--)
|
||||||
*buf++ = __arch_getw(addr);
|
*buf++ = __arch_getw(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern inline void __raw_readsl(unsigned int addr, void *data, int longlen)
|
extern inline void __raw_readsl(unsigned long addr, void *data, int longlen)
|
||||||
{
|
{
|
||||||
uint32_t *buf = (uint32_t *)data;
|
uint32_t *buf = (uint32_t *)data;
|
||||||
while(longlen--)
|
while(longlen--)
|
||||||
|
|
|
@ -54,5 +54,58 @@
|
||||||
bcs 1b
|
bcs 1b
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
/*
|
||||||
|
* Register aliases.
|
||||||
|
*/
|
||||||
|
lr .req x30
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Branch according to exception level
|
||||||
|
*/
|
||||||
|
.macro switch_el, xreg, el3_label, el2_label, el1_label
|
||||||
|
mrs \xreg, CurrentEL
|
||||||
|
cmp \xreg, 0xc
|
||||||
|
b.eq \el3_label
|
||||||
|
cmp \xreg, 0x8
|
||||||
|
b.eq \el2_label
|
||||||
|
cmp \xreg, 0x4
|
||||||
|
b.eq \el1_label
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Branch if current processor is a slave,
|
||||||
|
* choose processor with all zero affinity value as the master.
|
||||||
|
*/
|
||||||
|
.macro branch_if_slave, xreg, slave_label
|
||||||
|
mrs \xreg, mpidr_el1
|
||||||
|
tst \xreg, #0xff /* Test Affinity 0 */
|
||||||
|
b.ne \slave_label
|
||||||
|
lsr \xreg, \xreg, #8
|
||||||
|
tst \xreg, #0xff /* Test Affinity 1 */
|
||||||
|
b.ne \slave_label
|
||||||
|
lsr \xreg, \xreg, #8
|
||||||
|
tst \xreg, #0xff /* Test Affinity 2 */
|
||||||
|
b.ne \slave_label
|
||||||
|
lsr \xreg, \xreg, #16
|
||||||
|
tst \xreg, #0xff /* Test Affinity 3 */
|
||||||
|
b.ne \slave_label
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Branch if current processor is a master,
|
||||||
|
* choose processor with all zero affinity value as the master.
|
||||||
|
*/
|
||||||
|
.macro branch_if_master, xreg1, xreg2, master_label
|
||||||
|
mrs \xreg1, mpidr_el1
|
||||||
|
lsr \xreg2, \xreg1, #32
|
||||||
|
lsl \xreg1, \xreg1, #40
|
||||||
|
lsr \xreg1, \xreg1, #40
|
||||||
|
orr \xreg1, \xreg1, \xreg2
|
||||||
|
cbz \xreg1, \master_label
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
#endif /* __ASM_ARM_MACRO_H__ */
|
#endif /* __ASM_ARM_MACRO_H__ */
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#ifndef __ARCH_ARM_POSIX_TYPES_H
|
#ifndef __ARCH_ARM_POSIX_TYPES_H
|
||||||
#define __ARCH_ARM_POSIX_TYPES_H
|
#define __ARCH_ARM_POSIX_TYPES_H
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is generally used by user-level software, so you need to
|
* This file is generally used by user-level software, so you need to
|
||||||
* be a little careful about namespace pollution etc. Also, we cannot
|
* be a little careful about namespace pollution etc. Also, we cannot
|
||||||
|
@ -28,9 +30,17 @@ typedef int __kernel_pid_t;
|
||||||
typedef unsigned short __kernel_ipc_pid_t;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
typedef unsigned short __kernel_uid_t;
|
typedef unsigned short __kernel_uid_t;
|
||||||
typedef unsigned short __kernel_gid_t;
|
typedef unsigned short __kernel_gid_t;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
typedef unsigned long __kernel_size_t;
|
||||||
|
typedef long __kernel_ssize_t;
|
||||||
|
typedef long __kernel_ptrdiff_t;
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
typedef unsigned int __kernel_size_t;
|
typedef unsigned int __kernel_size_t;
|
||||||
typedef int __kernel_ssize_t;
|
typedef int __kernel_ssize_t;
|
||||||
typedef int __kernel_ptrdiff_t;
|
typedef int __kernel_ptrdiff_t;
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
typedef long __kernel_time_t;
|
typedef long __kernel_time_t;
|
||||||
typedef long __kernel_suseconds_t;
|
typedef long __kernel_suseconds_t;
|
||||||
typedef long __kernel_clock_t;
|
typedef long __kernel_clock_t;
|
||||||
|
|
|
@ -10,6 +10,25 @@
|
||||||
#ifndef __ASM_PROC_PTRACE_H
|
#ifndef __ASM_PROC_PTRACE_H
|
||||||
#define __ASM_PROC_PTRACE_H
|
#define __ASM_PROC_PTRACE_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
|
||||||
|
#define PCMASK 0
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This struct defines the way the registers are stored
|
||||||
|
* on the stack during an exception.
|
||||||
|
*/
|
||||||
|
struct pt_regs {
|
||||||
|
unsigned long elr;
|
||||||
|
unsigned long regs[31];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#define USR26_MODE 0x00
|
#define USR26_MODE 0x00
|
||||||
#define FIQ26_MODE 0x01
|
#define FIQ26_MODE 0x01
|
||||||
#define IRQ26_MODE 0x02
|
#define IRQ26_MODE 0x02
|
||||||
|
@ -104,4 +123,6 @@ static inline int valid_user_regs(struct pt_regs *regs)
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,60 @@
|
||||||
/*
|
/*
|
||||||
* Save the current interrupt enable state & disable IRQs
|
* Save the current interrupt enable state & disable IRQs
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the current interrupt enable state
|
||||||
|
* and disable IRQs/FIQs
|
||||||
|
*/
|
||||||
|
#define local_irq_save(flags) \
|
||||||
|
({ \
|
||||||
|
asm volatile( \
|
||||||
|
"mrs %0, daif" \
|
||||||
|
"msr daifset, #3" \
|
||||||
|
: "=r" (flags) \
|
||||||
|
: \
|
||||||
|
: "memory"); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* restore saved IRQ & FIQ state
|
||||||
|
*/
|
||||||
|
#define local_irq_restore(flags) \
|
||||||
|
({ \
|
||||||
|
asm volatile( \
|
||||||
|
"msr daif, %0" \
|
||||||
|
: \
|
||||||
|
: "r" (flags) \
|
||||||
|
: "memory"); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable IRQs/FIQs
|
||||||
|
*/
|
||||||
|
#define local_irq_enable() \
|
||||||
|
({ \
|
||||||
|
asm volatile( \
|
||||||
|
"msr daifclr, #3" \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
: "memory"); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable IRQs/FIQs
|
||||||
|
*/
|
||||||
|
#define local_irq_disable() \
|
||||||
|
({ \
|
||||||
|
asm volatile( \
|
||||||
|
"msr daifset, #3" \
|
||||||
|
: \
|
||||||
|
: \
|
||||||
|
: "memory"); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#define local_irq_save(x) \
|
#define local_irq_save(x) \
|
||||||
({ \
|
({ \
|
||||||
unsigned long temp; \
|
unsigned long temp; \
|
||||||
|
@ -107,7 +161,10 @@
|
||||||
: "r" (x) \
|
: "r" (x) \
|
||||||
: "memory")
|
: "memory")
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
|
#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) || \
|
||||||
|
defined(CONFIG_ARM64)
|
||||||
/*
|
/*
|
||||||
* On the StrongARM, "swp" is terminally broken since it bypasses the
|
* On the StrongARM, "swp" is terminally broken since it bypasses the
|
||||||
* cache totally. This means that the cache becomes inconsistent, and,
|
* cache totally. This means that the cache becomes inconsistent, and,
|
||||||
|
|
|
@ -1,6 +1,86 @@
|
||||||
#ifndef __ASM_ARM_SYSTEM_H
|
#ifndef __ASM_ARM_SYSTEM_H
|
||||||
#define __ASM_ARM_SYSTEM_H
|
#define __ASM_ARM_SYSTEM_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCTLR_EL1/SCTLR_EL2/SCTLR_EL3 bits definitions
|
||||||
|
*/
|
||||||
|
#define CR_M (1 << 0) /* MMU enable */
|
||||||
|
#define CR_A (1 << 1) /* Alignment abort enable */
|
||||||
|
#define CR_C (1 << 2) /* Dcache enable */
|
||||||
|
#define CR_SA (1 << 3) /* Stack Alignment Check Enable */
|
||||||
|
#define CR_I (1 << 12) /* Icache enable */
|
||||||
|
#define CR_WXN (1 << 19) /* Write Permision Imply XN */
|
||||||
|
#define CR_EE (1 << 25) /* Exception (Big) Endian */
|
||||||
|
|
||||||
|
#define PGTABLE_SIZE (0x10000)
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#define isb() \
|
||||||
|
({asm volatile( \
|
||||||
|
"isb" : : : "memory"); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define wfi() \
|
||||||
|
({asm volatile( \
|
||||||
|
"wfi" : : : "memory"); \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline unsigned int current_el(void)
|
||||||
|
{
|
||||||
|
unsigned int el;
|
||||||
|
asm volatile("mrs %0, CurrentEL" : "=r" (el) : : "cc");
|
||||||
|
return el >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int get_sctlr(void)
|
||||||
|
{
|
||||||
|
unsigned int el, val;
|
||||||
|
|
||||||
|
el = current_el();
|
||||||
|
if (el == 1)
|
||||||
|
asm volatile("mrs %0, sctlr_el1" : "=r" (val) : : "cc");
|
||||||
|
else if (el == 2)
|
||||||
|
asm volatile("mrs %0, sctlr_el2" : "=r" (val) : : "cc");
|
||||||
|
else
|
||||||
|
asm volatile("mrs %0, sctlr_el3" : "=r" (val) : : "cc");
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_sctlr(unsigned int val)
|
||||||
|
{
|
||||||
|
unsigned int el;
|
||||||
|
|
||||||
|
el = current_el();
|
||||||
|
if (el == 1)
|
||||||
|
asm volatile("msr sctlr_el1, %0" : : "r" (val) : "cc");
|
||||||
|
else if (el == 2)
|
||||||
|
asm volatile("msr sctlr_el2, %0" : : "r" (val) : "cc");
|
||||||
|
else
|
||||||
|
asm volatile("msr sctlr_el3, %0" : : "r" (val) : "cc");
|
||||||
|
|
||||||
|
asm volatile("isb");
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asm_flush_dcache_all(void);
|
||||||
|
void __asm_flush_dcache_range(u64 start, u64 end);
|
||||||
|
void __asm_invalidate_tlb_all(void);
|
||||||
|
void __asm_invalidate_icache_all(void);
|
||||||
|
|
||||||
|
void armv8_switch_to_el2(void);
|
||||||
|
void armv8_switch_to_el1(void);
|
||||||
|
void gic_init(void);
|
||||||
|
void gic_send_sgi(unsigned long sgino);
|
||||||
|
void wait_for_wakeup(void);
|
||||||
|
void smp_kick_all_cpus(void);
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#define CPU_ARCH_UNKNOWN 0
|
#define CPU_ARCH_UNKNOWN 0
|
||||||
|
@ -45,6 +125,8 @@
|
||||||
#define CR_AFE (1 << 29) /* Access flag enable */
|
#define CR_AFE (1 << 29) /* Access flag enable */
|
||||||
#define CR_TE (1 << 30) /* Thumb exception enable */
|
#define CR_TE (1 << 30) /* Thumb exception enable */
|
||||||
|
|
||||||
|
#define PGTABLE_SIZE (4096 * 4)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used to ensure the compiler did actually allocate the register we
|
* This is used to ensure the compiler did actually allocate the register we
|
||||||
* asked it for some inline assembly sequences. Apparently we can't trust
|
* asked it for some inline assembly sequences. Apparently we can't trust
|
||||||
|
@ -132,4 +214,6 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,7 +39,11 @@ typedef unsigned int u32;
|
||||||
typedef signed long long s64;
|
typedef signed long long s64;
|
||||||
typedef unsigned long long u64;
|
typedef unsigned long long u64;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
#define BITS_PER_LONG 64
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
#define BITS_PER_LONG 32
|
#define BITS_PER_LONG 32
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
|
|
||||||
/* Dma addresses are 32-bits wide. */
|
/* Dma addresses are 32-bits wide. */
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ typedef struct bd_info {
|
||||||
#endif /* !CONFIG_SYS_GENERIC_BOARD */
|
#endif /* !CONFIG_SYS_GENERIC_BOARD */
|
||||||
|
|
||||||
/* For image.h:image_check_target_arch() */
|
/* For image.h:image_check_target_arch() */
|
||||||
|
#ifndef CONFIG_ARM64
|
||||||
#define IH_ARCH_DEFAULT IH_ARCH_ARM
|
#define IH_ARCH_DEFAULT IH_ARCH_ARM
|
||||||
|
#else
|
||||||
|
#define IH_ARCH_DEFAULT IH_ARCH_ARM64
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _U_BOOT_H_ */
|
#endif /* _U_BOOT_H_ */
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
/*
|
/*
|
||||||
* Select endianness
|
* Select endianness
|
||||||
*/
|
*/
|
||||||
#ifndef __ARMEB__
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
#define get_unaligned __get_unaligned_le
|
#define get_unaligned __get_unaligned_le
|
||||||
#define put_unaligned __put_unaligned_le
|
#define put_unaligned __put_unaligned_le
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -17,14 +17,22 @@ lib-y += _umodsi3.o
|
||||||
lib-y += div0.o
|
lib-y += div0.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj-y += crt0.o
|
ifdef CONFIG_ARM64
|
||||||
|
obj-y += crt0_64.o
|
||||||
|
else
|
||||||
|
obj-y += crt0.o
|
||||||
|
endif
|
||||||
|
|
||||||
ifndef CONFIG_SPL_BUILD
|
ifndef CONFIG_SPL_BUILD
|
||||||
obj-y += relocate.o
|
ifdef CONFIG_ARM64
|
||||||
|
obj-y += relocate_64.o
|
||||||
|
else
|
||||||
|
obj-y += relocate.o
|
||||||
|
endif
|
||||||
ifndef CONFIG_SYS_GENERIC_BOARD
|
ifndef CONFIG_SYS_GENERIC_BOARD
|
||||||
obj-y += board.o
|
obj-y += board.o
|
||||||
endif
|
endif
|
||||||
obj-y += sections.o
|
obj-y += sections.o
|
||||||
|
|
||||||
obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
|
obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
|
||||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||||
|
@ -35,11 +43,17 @@ else
|
||||||
obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
|
obj-$(CONFIG_SPL_FRAMEWORK) += spl.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_ARM64
|
||||||
|
obj-y += interrupts_64.o
|
||||||
|
else
|
||||||
obj-y += interrupts.o
|
obj-y += interrupts.o
|
||||||
|
endif
|
||||||
obj-y += reset.o
|
obj-y += reset.o
|
||||||
|
|
||||||
obj-y += cache.o
|
obj-y += cache.o
|
||||||
|
ifndef CONFIG_ARM64
|
||||||
obj-y += cache-cp15.o
|
obj-y += cache-cp15.o
|
||||||
|
endif
|
||||||
|
|
||||||
# For EABI conformant tool chains, provide eabi_compat()
|
# For EABI conformant tool chains, provide eabi_compat()
|
||||||
ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
|
ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
|
||||||
|
|
|
@ -344,7 +344,7 @@ void board_init_f(ulong bootflag)
|
||||||
|
|
||||||
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
|
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
|
||||||
/* reserve TLB table */
|
/* reserve TLB table */
|
||||||
gd->arch.tlb_size = 4096 * 4;
|
gd->arch.tlb_size = PGTABLE_SIZE;
|
||||||
addr -= gd->arch.tlb_size;
|
addr -= gd->arch.tlb_size;
|
||||||
|
|
||||||
/* round down to next 64 kB limit */
|
/* round down to next 64 kB limit */
|
||||||
|
@ -419,6 +419,7 @@ void board_init_f(ulong bootflag)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_ARM64
|
||||||
/* setup stackpointer for exeptions */
|
/* setup stackpointer for exeptions */
|
||||||
gd->irq_sp = addr_sp;
|
gd->irq_sp = addr_sp;
|
||||||
#ifdef CONFIG_USE_IRQ
|
#ifdef CONFIG_USE_IRQ
|
||||||
|
@ -431,6 +432,10 @@ void board_init_f(ulong bootflag)
|
||||||
|
|
||||||
/* 8-byte alignment for ABI compliance */
|
/* 8-byte alignment for ABI compliance */
|
||||||
addr_sp &= ~0x07;
|
addr_sp &= ~0x07;
|
||||||
|
#else /* CONFIG_ARM64 */
|
||||||
|
/* 16-byte alignment for ABI compliance */
|
||||||
|
addr_sp &= ~0x0f;
|
||||||
|
#endif /* CONFIG_ARM64 */
|
||||||
#else
|
#else
|
||||||
addr_sp += 128; /* leave 32 words for abort-stack */
|
addr_sp += 128; /* leave 32 words for abort-stack */
|
||||||
gd->irq_sp = addr_sp;
|
gd->irq_sp = addr_sp;
|
||||||
|
|
|
@ -196,6 +196,14 @@ static void do_nonsec_virt_switch(void)
|
||||||
debug("entered non-secure state\n");
|
debug("entered non-secure state\n");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
smp_kick_all_cpus();
|
||||||
|
armv8_switch_to_el2();
|
||||||
|
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
|
||||||
|
armv8_switch_to_el1();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subcommand: PREP */
|
/* Subcommand: PREP */
|
||||||
|
@ -240,6 +248,21 @@ static void boot_prep_linux(bootm_headers_t *images)
|
||||||
/* Subcommand: GO */
|
/* Subcommand: GO */
|
||||||
static void boot_jump_linux(bootm_headers_t *images, int flag)
|
static void boot_jump_linux(bootm_headers_t *images, int flag)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
void (*kernel_entry)(void *fdt_addr);
|
||||||
|
int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
|
||||||
|
|
||||||
|
kernel_entry = (void (*)(void *fdt_addr))images->ep;
|
||||||
|
|
||||||
|
debug("## Transferring control to Linux (at address %lx)...\n",
|
||||||
|
(ulong) kernel_entry);
|
||||||
|
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
|
||||||
|
|
||||||
|
announce_and_cleanup(fake);
|
||||||
|
|
||||||
|
if (!fake)
|
||||||
|
kernel_entry(images->ft_addr);
|
||||||
|
#else
|
||||||
unsigned long machid = gd->bd->bi_arch_number;
|
unsigned long machid = gd->bd->bi_arch_number;
|
||||||
char *s;
|
char *s;
|
||||||
void (*kernel_entry)(int zero, int arch, uint params);
|
void (*kernel_entry)(int zero, int arch, uint params);
|
||||||
|
@ -266,6 +289,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
|
||||||
|
|
||||||
if (!fake)
|
if (!fake)
|
||||||
kernel_entry(0, machid, r2);
|
kernel_entry(0, machid, r2);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main Entry point for arm bootm implementation
|
/* Main Entry point for arm bootm implementation
|
||||||
|
|
113
arch/arm/lib/crt0_64.S
Normal file
113
arch/arm/lib/crt0_64.S
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* crt0 - C-runtime startup Code for AArch64 U-Boot
|
||||||
|
*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* (C) Copyright 2012
|
||||||
|
* Albert ARIBAUD <albert.u.boot@aribaud.net>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <asm/macro.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file handles the target-independent stages of the U-Boot
|
||||||
|
* start-up where a C runtime environment is needed. Its entry point
|
||||||
|
* is _main and is branched into from the target's start.S file.
|
||||||
|
*
|
||||||
|
* _main execution sequence is:
|
||||||
|
*
|
||||||
|
* 1. Set up initial environment for calling board_init_f().
|
||||||
|
* This environment only provides a stack and a place to store
|
||||||
|
* the GD ('global data') structure, both located in some readily
|
||||||
|
* available RAM (SRAM, locked cache...). In this context, VARIABLE
|
||||||
|
* global data, initialized or not (BSS), are UNAVAILABLE; only
|
||||||
|
* CONSTANT initialized data are available.
|
||||||
|
*
|
||||||
|
* 2. Call board_init_f(). This function prepares the hardware for
|
||||||
|
* execution from system RAM (DRAM, DDR...) As system RAM may not
|
||||||
|
* be available yet, , board_init_f() must use the current GD to
|
||||||
|
* store any data which must be passed on to later stages. These
|
||||||
|
* data include the relocation destination, the future stack, and
|
||||||
|
* the future GD location.
|
||||||
|
*
|
||||||
|
* (the following applies only to non-SPL builds)
|
||||||
|
*
|
||||||
|
* 3. Set up intermediate environment where the stack and GD are the
|
||||||
|
* ones allocated by board_init_f() in system RAM, but BSS and
|
||||||
|
* initialized non-const data are still not available.
|
||||||
|
*
|
||||||
|
* 4. Call relocate_code(). This function relocates U-Boot from its
|
||||||
|
* current location into the relocation destination computed by
|
||||||
|
* board_init_f().
|
||||||
|
*
|
||||||
|
* 5. Set up final environment for calling board_init_r(). This
|
||||||
|
* environment has BSS (initialized to 0), initialized non-const
|
||||||
|
* data (initialized to their intended value), and stack in system
|
||||||
|
* RAM. GD has retained values set by board_init_f(). Some CPUs
|
||||||
|
* have some work left to do at this point regarding memory, so
|
||||||
|
* call c_runtime_cpu_setup.
|
||||||
|
*
|
||||||
|
* 6. Branch to board_init_r().
|
||||||
|
*/
|
||||||
|
|
||||||
|
ENTRY(_main)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up initial C runtime environment and call board_init_f(0).
|
||||||
|
*/
|
||||||
|
ldr x0, =(CONFIG_SYS_INIT_SP_ADDR)
|
||||||
|
sub x0, x0, #GD_SIZE /* allocate one GD above SP */
|
||||||
|
bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
|
||||||
|
mov x18, sp /* GD is above SP */
|
||||||
|
mov x0, #0
|
||||||
|
bl board_init_f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up intermediate environment (new sp and gd) and call
|
||||||
|
* relocate_code(addr_moni). Trick here is that we'll return
|
||||||
|
* 'here' but relocated.
|
||||||
|
*/
|
||||||
|
ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */
|
||||||
|
bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */
|
||||||
|
ldr x18, [x18, #GD_BD] /* x18 <- gd->bd */
|
||||||
|
sub x18, x18, #GD_SIZE /* new GD is below bd */
|
||||||
|
|
||||||
|
adr lr, relocation_return
|
||||||
|
ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */
|
||||||
|
add lr, lr, x9 /* new return address after relocation */
|
||||||
|
ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */
|
||||||
|
b relocate_code
|
||||||
|
|
||||||
|
relocation_return:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up final (full) environment
|
||||||
|
*/
|
||||||
|
bl c_runtime_cpu_setup /* still call old routine */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear BSS section
|
||||||
|
*/
|
||||||
|
ldr x0, =__bss_start /* this is auto-relocated! */
|
||||||
|
ldr x1, =__bss_end /* this is auto-relocated! */
|
||||||
|
mov x2, #0
|
||||||
|
clear_loop:
|
||||||
|
str x2, [x0]
|
||||||
|
add x0, x0, #8
|
||||||
|
cmp x0, x1
|
||||||
|
b.lo clear_loop
|
||||||
|
|
||||||
|
/* call board_init_r(gd_t *id, ulong dest_addr) */
|
||||||
|
mov x0, x18 /* gd_t */
|
||||||
|
ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */
|
||||||
|
b board_init_r /* PC relative jump */
|
||||||
|
|
||||||
|
/* NOTREACHED - board_init_r() does not return */
|
||||||
|
|
||||||
|
ENDPROC(_main)
|
120
arch/arm/lib/interrupts_64.c
Normal file
120
arch/arm/lib/interrupts_64.c
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
|
|
||||||
|
int interrupt_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_interrupts(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int disable_interrupts(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_regs(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("ELR: %lx\n", regs->elr);
|
||||||
|
printf("LR: %lx\n", regs->regs[30]);
|
||||||
|
for (i = 0; i < 29; i += 2)
|
||||||
|
printf("x%-2d: %016lx x%-2d: %016lx\n",
|
||||||
|
i, regs->regs[i], i+1, regs->regs[i+1]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_bad_sync handles the impossible case in the Synchronous Abort vector.
|
||||||
|
*/
|
||||||
|
void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_bad_irq handles the impossible case in the Irq vector.
|
||||||
|
*/
|
||||||
|
void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_bad_fiq handles the impossible case in the Fiq vector.
|
||||||
|
*/
|
||||||
|
void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_bad_error handles the impossible case in the Error vector.
|
||||||
|
*/
|
||||||
|
void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_sync handles the Synchronous Abort exception.
|
||||||
|
*/
|
||||||
|
void do_sync(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_irq handles the Irq exception.
|
||||||
|
*/
|
||||||
|
void do_irq(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("\"Irq\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_fiq handles the Fiq exception.
|
||||||
|
*/
|
||||||
|
void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("\"Fiq\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_error handles the Error exception.
|
||||||
|
* Errors are more likely to be processor specific,
|
||||||
|
* it is defined with weak attribute and can be redefined
|
||||||
|
* in processor specific code.
|
||||||
|
*/
|
||||||
|
void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
|
||||||
|
{
|
||||||
|
printf("\"Error\" handler, esr 0x%08x\n", esr);
|
||||||
|
show_regs(pt_regs);
|
||||||
|
panic("Resetting CPU ...\n");
|
||||||
|
}
|
58
arch/arm/lib/relocate_64.S
Normal file
58
arch/arm/lib/relocate_64.S
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* relocate - common relocation function for AArch64 U-Boot
|
||||||
|
*
|
||||||
|
* (C) Copyright 2013
|
||||||
|
* Albert ARIBAUD <albert.u.boot@aribaud.net>
|
||||||
|
* David Feng <fenghua@phytium.com.cn>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm-offsets.h>
|
||||||
|
#include <config.h>
|
||||||
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void relocate_code (addr_moni)
|
||||||
|
*
|
||||||
|
* This function relocates the monitor code.
|
||||||
|
* x0 holds the destination address.
|
||||||
|
*/
|
||||||
|
ENTRY(relocate_code)
|
||||||
|
/*
|
||||||
|
* Copy u-boot from flash to RAM
|
||||||
|
*/
|
||||||
|
ldr x1, =__image_copy_start /* x1 <- SRC &__image_copy_start */
|
||||||
|
subs x9, x0, x1 /* x9 <- relocation offset */
|
||||||
|
b.eq relocate_done /* skip relocation */
|
||||||
|
ldr x2, =__image_copy_end /* x2 <- SRC &__image_copy_end */
|
||||||
|
|
||||||
|
copy_loop:
|
||||||
|
ldp x10, x11, [x1], #16 /* copy from source address [x1] */
|
||||||
|
stp x10, x11, [x0], #16 /* copy to target address [x0] */
|
||||||
|
cmp x1, x2 /* until source end address [x2] */
|
||||||
|
b.lo copy_loop
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix .rela.dyn relocations
|
||||||
|
*/
|
||||||
|
ldr x2, =__rel_dyn_start /* x2 <- SRC &__rel_dyn_start */
|
||||||
|
ldr x3, =__rel_dyn_end /* x3 <- SRC &__rel_dyn_end */
|
||||||
|
fixloop:
|
||||||
|
ldp x0, x1, [x2], #16 /* (x0,x1) <- (SRC location, fixup) */
|
||||||
|
ldr x4, [x2], #8 /* x4 <- addend */
|
||||||
|
and x1, x1, #0xffffffff
|
||||||
|
cmp x1, #1027 /* relative fixup? */
|
||||||
|
bne fixnext
|
||||||
|
|
||||||
|
/* relative fix: store addend plus offset at dest location */
|
||||||
|
add x0, x0, x9
|
||||||
|
add x4, x4, x9
|
||||||
|
str x4, [x0]
|
||||||
|
fixnext:
|
||||||
|
cmp x2, x3
|
||||||
|
b.lo fixloop
|
||||||
|
|
||||||
|
relocate_done:
|
||||||
|
ret
|
||||||
|
ENDPROC(relocate_code)
|
|
@ -81,6 +81,7 @@ static const table_entry_t uimage_arch[] = {
|
||||||
{ IH_ARCH_NDS32, "nds32", "NDS32", },
|
{ IH_ARCH_NDS32, "nds32", "NDS32", },
|
||||||
{ IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",},
|
{ IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",},
|
||||||
{ IH_ARCH_SANDBOX, "sandbox", "Sandbox", },
|
{ IH_ARCH_SANDBOX, "sandbox", "Sandbox", },
|
||||||
|
{ IH_ARCH_ARM64, "arm64", "AArch64", },
|
||||||
{ -1, "", "", },
|
{ -1, "", "", },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
46
doc/README.arm64
Normal file
46
doc/README.arm64
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
U-boot for arm64
|
||||||
|
|
||||||
|
Summary
|
||||||
|
=======
|
||||||
|
No hardware platform of arm64 is available now. The u-boot is
|
||||||
|
simulated on Foundation Model and Fast Model for ARMv8.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
=====
|
||||||
|
|
||||||
|
1. Currenly, u-boot run at the highest exception level processor
|
||||||
|
supported and jump to EL2 or optionally EL1 before enter OS.
|
||||||
|
|
||||||
|
2. U-boot for arm64 is compiled with AArch64-gcc. AArch64-gcc
|
||||||
|
use rela relocation format, a tool(tools/relocate-rela) by Scott Wood
|
||||||
|
is used to encode the initial addend of rela to u-boot.bin. After running,
|
||||||
|
the u-boot will be relocated to destination again.
|
||||||
|
|
||||||
|
3. Fdt should be placed at a 2-megabyte boundary and within the first 512
|
||||||
|
megabytes from the start of the kernel image. So, fdt_high should be
|
||||||
|
defined specially.
|
||||||
|
Please reference linux/Documentation/arm64/booting.txt for detail.
|
||||||
|
|
||||||
|
4. Spin-table is used to wake up secondary processors. One location
|
||||||
|
(or per processor location) is defined to hold the kernel entry point
|
||||||
|
for secondary processors. It must be ensured that the location is
|
||||||
|
accessible and zero immediately after secondary processor
|
||||||
|
enter slave_cpu branch execution in start.S. The location address
|
||||||
|
is encoded in cpu node of DTS. Linux kernel store the entry point
|
||||||
|
of secondary processors to it and send event to wakeup secondary
|
||||||
|
processors.
|
||||||
|
Please reference linux/Documentation/arm64/booting.txt for detail.
|
||||||
|
|
||||||
|
5. Generic board is supported.
|
||||||
|
|
||||||
|
6. CONFIG_ARM64 instead of CONFIG_ARMV8 is used to distinguish aarch64 and
|
||||||
|
aarch32 specific codes.
|
||||||
|
|
||||||
|
Contributor
|
||||||
|
===========
|
||||||
|
Tom Rini <trini@ti.com>
|
||||||
|
Scott Wood <scottwood@freescale.com>
|
||||||
|
York Sun <yorksun@freescale.com>
|
||||||
|
Simon Glass <sjg@chromium.org>
|
||||||
|
Sharma Bhupesh <bhupesh.sharma@freescale.com>
|
||||||
|
Rob Herring <robherring2@gmail.com>
|
|
@ -39,6 +39,20 @@ gd_t *global_data;
|
||||||
" bctr\n" \
|
" bctr\n" \
|
||||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
|
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
|
||||||
#elif defined(CONFIG_ARM)
|
#elif defined(CONFIG_ARM)
|
||||||
|
#ifdef CONFIG_ARM64
|
||||||
|
/*
|
||||||
|
* x18 holds the pointer to the global_data, x9 is a call-clobbered
|
||||||
|
* register
|
||||||
|
*/
|
||||||
|
#define EXPORT_FUNC(x) \
|
||||||
|
asm volatile ( \
|
||||||
|
" .globl " #x "\n" \
|
||||||
|
#x ":\n" \
|
||||||
|
" ldr x9, [x18, %0]\n" \
|
||||||
|
" ldr x9, [x9, %1]\n" \
|
||||||
|
" br x9\n" \
|
||||||
|
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "x9");
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* r9 holds the pointer to the global_data, ip is a call-clobbered
|
* r9 holds the pointer to the global_data, ip is a call-clobbered
|
||||||
* register
|
* register
|
||||||
|
@ -50,6 +64,7 @@ gd_t *global_data;
|
||||||
" ldr ip, [r9, %0]\n" \
|
" ldr ip, [r9, %0]\n" \
|
||||||
" ldr pc, [ip, %1]\n" \
|
" ldr pc, [ip, %1]\n" \
|
||||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
|
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
|
||||||
|
#endif
|
||||||
#elif defined(CONFIG_MIPS)
|
#elif defined(CONFIG_MIPS)
|
||||||
/*
|
/*
|
||||||
* k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
|
* k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
|
||||||
|
|
|
@ -156,6 +156,7 @@ struct lmb;
|
||||||
#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */
|
#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */
|
||||||
#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */
|
#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */
|
||||||
#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */
|
#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */
|
||||||
|
#define IH_ARCH_ARM64 22 /* ARM64 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Image Types
|
* Image Types
|
||||||
|
|
Loading…
Add table
Reference in a new issue