[U-Boot] [PATCH v13 0/6] arm64 patch

From: David Feng fenghua@phytium.com.cn
Changes for v13: - fix the bug of board_r.c and arm/lib/board.c due to CONFIG_NEED_MANUAL_RELOC. adjust initr_serial() in board_r.c to the first entry of init_sequence_r[] and relocate serial_initialize() in arm/lib/board.c, routines of serial_device should be relocated firstly by serial_initialize(), so that printf access the correct puts function, otherwise uninitialized serial_current will be selected as the output device. - fix the bug of dcache_enable(). after mmu_setup the sctrl register value should be fetched again because it has been modifed by mmu_seup() function. This bug is find by York Sun yorksun@freescale.com. - add macro branch_if_slave to macro.h, it choose processor with all zero affinity value as the master and is used in start.S.
Changes for v12: - custom the patches to new format boards.cfg.
Changes for v11: - Replace CONFIG_ARMV8 with CONFIG_ARM64. Currently, it's hard to distinguish what is armv8 specific and what is aarch64 specific, so we use CONFIG_ARM64 only, no CONFIG_ARMV8 used. - rename README.armv8 with README.arm64 and make some modification.
Changes for v10: - add weak definition to include/linux/linkage.h and make setup_el2/setup_el3/lowlevel_init weak routines, so them can be easily overridden by processor specific code. - modify s-o-f of 0002-board-support-of-vexpress_aemv8a which use wrong mail address of Bhupesh Sharma.
Changes for v9: - add Signed-off-by information to patch "board support of vexpress_aemv8a" which SMC91111 support is integrated from Sharma Bhupesh's patch. - adjust pt_regs struct and add exception state preservation in exception.S.
Changes for v8: - Integrate SMC91111 patch of sharma bhupesh. - remove v8_outer_cache* which is not need currently. - Change license tag. - Mov crt0.S/relocate.S/interrupts.c to arm/lib and rename them with _64 suffix. - Make el3/el2 initializing process of start.S as two separate routines. It could be easier to be replaced with processor specific codes. - Remove exception stack save and restore routine, it is unnecessary now. - simplify __weak function declaration.
Changes for v7: - Check the patches with checkpatch.pl and get rid of almost all warnings. There are a few warnings still, but I think it should be that. - change printf format in cmd_pxe.c, use %zd indtead of %ld to format size_t type variable. - add macro PGTABLE_SIZE to identify tlb table size.
Changes for v6: - Make modification to inappropriate licensed file and bugs according to ScottWood's advice. Thanks Scott for his checking to these patches. - Enable u-boot's running at EL1. - Get rid of compiling warnings originated from cmd_pxe.c.
Changes for v5: - fix the generic board_f.c, remove zero_global_data from init_sequence_f array and move it to board_init_f() function with CONFIG_X86 switch. The previous fixup is inaccurate. - Replace __ARMEB__ with __AARCH64EB__ in byteorder.h and unaligned.h, gcc for aarch64 use __AARCH64EB__ and __AARCH64EL__ to identify endian. - Some modification to README.armv8
Changes for v4: - merge arm64 to arm architecture.
David Feng (6): core support of arm64 board support of vexpress_aemv8a generic board patch of manual reloc and zero gd_t 64bit initrd start address support remove compiling warnings add weak entry definition
arch/arm/config.mk | 4 + arch/arm/cpu/armv8/Makefile | 38 +++ arch/arm/cpu/armv8/cache.S | 130 +++++++++ arch/arm/cpu/armv8/cache_v8.c | 218 +++++++++++++++ arch/arm/cpu/armv8/config.mk | 16 ++ arch/arm/cpu/armv8/cpu.c | 67 +++++ arch/arm/cpu/armv8/exceptions.S | 115 ++++++++ arch/arm/cpu/armv8/start.S | 234 ++++++++++++++++ arch/arm/cpu/armv8/timer.c | 80 ++++++ arch/arm/cpu/armv8/tlb.S | 30 +++ arch/arm/cpu/armv8/u-boot.lds | 71 +++++ arch/arm/include/asm/arch-armv8/gpio.h | 11 + arch/arm/include/asm/arch-armv8/mmu.h | 110 ++++++++ arch/arm/include/asm/byteorder.h | 12 + arch/arm/include/asm/cache.h | 5 + arch/arm/include/asm/config.h | 10 + arch/arm/include/asm/global_data.h | 6 +- arch/arm/include/asm/io.h | 15 +- arch/arm/include/asm/macro.h | 39 +++ arch/arm/include/asm/posix_types.h | 10 + arch/arm/include/asm/proc-armv/ptrace.h | 21 ++ arch/arm/include/asm/proc-armv/system.h | 59 ++++- arch/arm/include/asm/system.h | 77 ++++++ arch/arm/include/asm/types.h | 4 + arch/arm/include/asm/u-boot.h | 4 + arch/arm/include/asm/unaligned.h | 2 +- arch/arm/lib/Makefile | 14 + arch/arm/lib/board.c | 25 +- arch/arm/lib/bootm.c | 16 ++ arch/arm/lib/crt0_64.S | 116 ++++++++ arch/arm/lib/interrupts_64.c | 120 +++++++++ arch/arm/lib/relocate_64.S | 57 ++++ board/armltd/dts/vexpress64.dts | 439 +++++++++++++++++++++++++++++++ board/armltd/vexpress64/Makefile | 27 ++ board/armltd/vexpress64/vexpress64.c | 70 +++++ boards.cfg | 1 + common/board_f.c | 18 +- common/board_r.c | 20 +- common/cmd_pxe.c | 4 +- common/fdt_support.c | 66 ++--- common/image.c | 1 + doc/README.arm64 | 33 +++ examples/standalone/stubs.c | 15 ++ include/configs/vexpress_aemv8a.h | 191 ++++++++++++++ include/image.h | 1 + include/linux/linkage.h | 4 + 46 files changed, 2573 insertions(+), 53 deletions(-) create mode 100644 arch/arm/cpu/armv8/Makefile create mode 100644 arch/arm/cpu/armv8/cache.S create mode 100644 arch/arm/cpu/armv8/cache_v8.c create mode 100644 arch/arm/cpu/armv8/config.mk create mode 100644 arch/arm/cpu/armv8/cpu.c create mode 100644 arch/arm/cpu/armv8/exceptions.S create mode 100644 arch/arm/cpu/armv8/start.S create mode 100644 arch/arm/cpu/armv8/timer.c create mode 100644 arch/arm/cpu/armv8/tlb.S create mode 100644 arch/arm/cpu/armv8/u-boot.lds create mode 100644 arch/arm/include/asm/arch-armv8/gpio.h create mode 100644 arch/arm/include/asm/arch-armv8/mmu.h create mode 100644 arch/arm/lib/crt0_64.S create mode 100644 arch/arm/lib/interrupts_64.c create mode 100644 arch/arm/lib/relocate_64.S create mode 100644 board/armltd/dts/vexpress64.dts create mode 100644 board/armltd/vexpress64/Makefile create mode 100644 board/armltd/vexpress64/vexpress64.c create mode 100644 doc/README.arm64 create mode 100644 include/configs/vexpress_aemv8a.h

From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn --- arch/arm/config.mk | 4 + arch/arm/cpu/armv8/Makefile | 38 +++++ arch/arm/cpu/armv8/cache.S | 130 +++++++++++++++++ arch/arm/cpu/armv8/cache_v8.c | 218 ++++++++++++++++++++++++++++ arch/arm/cpu/armv8/config.mk | 16 +++ arch/arm/cpu/armv8/cpu.c | 67 +++++++++ arch/arm/cpu/armv8/exceptions.S | 115 +++++++++++++++ arch/arm/cpu/armv8/start.S | 234 +++++++++++++++++++++++++++++++ arch/arm/cpu/armv8/timer.c | 80 +++++++++++ arch/arm/cpu/armv8/tlb.S | 30 ++++ arch/arm/cpu/armv8/u-boot.lds | 71 ++++++++++ arch/arm/include/asm/arch-armv8/gpio.h | 11 ++ arch/arm/include/asm/arch-armv8/mmu.h | 110 +++++++++++++++ arch/arm/include/asm/byteorder.h | 12 ++ arch/arm/include/asm/cache.h | 5 + arch/arm/include/asm/config.h | 10 ++ arch/arm/include/asm/global_data.h | 6 +- arch/arm/include/asm/io.h | 15 +- arch/arm/include/asm/macro.h | 39 ++++++ arch/arm/include/asm/posix_types.h | 10 ++ arch/arm/include/asm/proc-armv/ptrace.h | 21 +++ arch/arm/include/asm/proc-armv/system.h | 59 +++++++- arch/arm/include/asm/system.h | 77 ++++++++++ arch/arm/include/asm/types.h | 4 + arch/arm/include/asm/u-boot.h | 4 + arch/arm/include/asm/unaligned.h | 2 +- arch/arm/lib/Makefile | 14 ++ arch/arm/lib/board.c | 25 +++- arch/arm/lib/bootm.c | 16 +++ arch/arm/lib/crt0_64.S | 116 +++++++++++++++ arch/arm/lib/interrupts_64.c | 120 ++++++++++++++++ arch/arm/lib/relocate_64.S | 57 ++++++++ common/image.c | 1 + doc/README.arm64 | 33 +++++ examples/standalone/stubs.c | 15 ++ include/image.h | 1 + 36 files changed, 1775 insertions(+), 11 deletions(-) create mode 100644 arch/arm/cpu/armv8/Makefile create mode 100644 arch/arm/cpu/armv8/cache.S create mode 100644 arch/arm/cpu/armv8/cache_v8.c create mode 100644 arch/arm/cpu/armv8/config.mk create mode 100644 arch/arm/cpu/armv8/cpu.c create mode 100644 arch/arm/cpu/armv8/exceptions.S create mode 100644 arch/arm/cpu/armv8/start.S create mode 100644 arch/arm/cpu/armv8/timer.c create mode 100644 arch/arm/cpu/armv8/tlb.S create mode 100644 arch/arm/cpu/armv8/u-boot.lds create mode 100644 arch/arm/include/asm/arch-armv8/gpio.h create mode 100644 arch/arm/include/asm/arch-armv8/mmu.h create mode 100644 arch/arm/lib/crt0_64.S create mode 100644 arch/arm/lib/interrupts_64.c create mode 100644 arch/arm/lib/relocate_64.S create mode 100644 doc/README.arm64
diff --git a/arch/arm/config.mk b/arch/arm/config.mk index ce3903b..95c07ad 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -74,7 +74,9 @@ endif endif
# needed for relocation +ifndef CONFIG_ARM64 LDFLAGS_u-boot += -pie +endif
# # FIXME: binutils versions < 2.22 have a bug in the assembler where @@ -95,6 +97,8 @@ endif endif
# check that only R_ARM_RELATIVE relocations are generated +ifndef CONFIG_ARM64 ifneq ($(CONFIG_SPL_BUILD),y) ALL-y += checkarmreloc endif +endif diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile new file mode 100644 index 0000000..b216f27 --- /dev/null +++ b/arch/arm/cpu/armv8/Makefile @@ -0,0 +1,38 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(CPU).o + +START := start.o + +COBJS += cpu.o +COBJS += timer.o +COBJS += cache_v8.o + +SOBJS += exceptions.o +SOBJS += cache.o +SOBJS += tlb.o + +SRCS := $(START:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S new file mode 100644 index 0000000..419f169 --- /dev/null +++ b/arch/arm/cpu/armv8/cache.S @@ -0,0 +1,130 @@ +/* + * (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/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 /* isb to sych the new cssr & csidr */ + mrs x6, ccsidr_el1 /* read the new ccsidr */ + and x2, x6, #7 /* x2 <- length of the cache lines */ + add x2, x2, #4 /* add 4 (line length offset) */ + mov x3, #0x3ff + and x3, x3, x6, lsr #3 /* x3 <- maximum number of way size */ + clz w5, w3 /* bit position of way size */ + mov x4, #0x7fff + and x4, x4, x1, lsr #13 /* x4 <- max number of the set size */ + /* x1 <- cache level << 1 */ + /* x2 <- line length offset */ + /* x3 <- number of cache ways */ + /* x4 <- number of cache sets */ + /* x5 <- bit position of way size */ + +loop_set: + mov x6, x3 /* create working copy of way size */ +loop_way: + lsl x7, x6, x5 + orr x9, x0, 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 + mov x15, lr + mrs x10, clidr_el1 /* read clidr */ + lsr x11, x10, #24 + and x11, x11, #0x7 /* x11 <- loc */ + cbz x11, finished /* if loc is 0, no need to clean */ + mov x0, #0 /* start flush at cache level 0 */ + /* x0 <- cache level */ + /* x10 <- clidr_el1 */ + /* x11 <- loc */ + +loop_level: + lsl x1, x0, #1 + add x1, x1, x0 /* x0 <- 3x 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 + +finished: + mov x0, #0 + msr csselr_el1, x0 /* swith back to cache level 0 */ + dsb sy + isb + mov lr, x15 + 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 /* read CTR */ + lsr x3, x3, #16 + and x3, x3, #0xf /* cache line size encoding */ + mov x2, #4 /* bytes per word */ + lsl x2, x2, x3 /* actual 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 D/unified line */ + 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) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c new file mode 100644 index 0000000..34426fd --- /dev/null +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -0,0 +1,218 @@ +/* + * (C) Copyright 2013 + * David Feng fenghua@phytium.com.cn + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/system.h> +#include <asm/arch/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 < (PAGE_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 = curent_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 + panic("Not Supported Exception Level"); + + /* 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); +} diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk new file mode 100644 index 0000000..9f36d59 --- /dev/null +++ b/arch/arm/cpu/armv8/config.mk @@ -0,0 +1,16 @@ +# +# (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) +PLATFORM_CPPFLAGS += -fpic diff --git a/arch/arm/cpu/armv8/cpu.c b/arch/arm/cpu/armv8/cpu.c new file mode 100644 index 0000000..83e73ab --- /dev/null +++ b/arch/arm/cpu/armv8/cpu.c @@ -0,0 +1,67 @@ +/* + * (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+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <linux/compiler.h> + +void __weak cpu_cache_initialization(void){} + +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ +#ifndef CONFIG_SPL_BUILD + disable_interrupts(); +#endif + + /* + * 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(); + + /* + * After D-cache is flushed and before it is disabled there may + * be some new valid entries brought into the cache. We are sure + * that these lines are not dirty and will not affect our execution. + * (because unwinding the call-stack and setting a bit in CP15 SCTRL + * is all we did during this. We have not pushed anything on to the + * stack. Neither have we affected any static data) + * So just invalidate the entire d-cache again to avoid coherency + * problems for kernel + */ + invalidate_dcache_all(); + + /* + * Some CPU need more cache attention before starting the kernel. + */ + cpu_cache_initialization(); + + return 0; +} diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S new file mode 100644 index 0000000..b2f62c9 --- /dev/null +++ b/arch/arm/cpu/armv8/exceptions.S @@ -0,0 +1,115 @@ +/* + * (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 EL1 or EL2 */ + mrs x11, CurrentEL + cmp x11, 0x4 + b.eq 1f + cmp x11, 0x8 + b.eq 2f + b 3f +1: mrs x1, esr_el1 + mrs x2, elr_el1 + b 3f +2: mrs x1, esr_el2 + mrs x2, elr_el2 +3: + 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 diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S new file mode 100644 index 0000000..28c8fe3 --- /dev/null +++ b/arch/arm/cpu/armv8/start.S @@ -0,0 +1,234 @@ +/* + * (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/arch/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 + */ + mrs x0, CurrentEL + cmp x0, #0xc + b.ne reset_nonsecure /* Not EL3 */ + + bl setup_el3 /* EL3 initialization */ + + /* + * MMU Disabled, iCache Disabled, dCache Disabled + */ +reset_nonsecure: + +#ifdef CONFIG_BOOTING_EL1 + switch_el1_el2 x0, 1f, 2f, 3f +1: b 3f +2: bl setup_el2 /* EL2 initialization */ +3: +#endif + + /* Initialize vBAR/CPACR_EL1/MDSCR_EL1 */ + adr x0, vectors + switch_el1_el2 x1, 1f, 2f, 3f +1: msr vbar_el1, x0 + mov x0, #3 << 20 + msr cpacr_el1, x0 /* Enable FP/SIMD */ + msr mdscr_el1, xzr + b 3f +2: msr vbar_el2, x0 +3: + + /* 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_slave x0, slave_cpu + + /* + * Master CPU + */ +master_cpu: + bl _main + + /* + * Slave CPUs + */ +slave_cpu: + wfe + ldr x1, =SECONDARY_CPU_MAILBOX + ldr x0, [x1] + cbz x0, slave_cpu + br x0 /* branch to the given address */ + +/*-------------------------------------------------------------------------*/ + +WEAK(setup_el3) + mov x0, #0x531 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */ + msr scr_el3, x0 + msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */ + + /* GIC initialization */ + branch_if_slave x0, 2f + + /* Master initialize distributor */ + ldr x1, =GIC_DIST_BASE /* GICD_CTLR */ + mov w0, #0x3 /* Enable Group0 & Group1 */ + str w0, [x1] + ldr w0, [x1, #0x4] /* GICD_TYPER */ + and w2, w0, #0x1f /* ITLinesNumber */ + add w2, w2, #0x1 /* Number of GICD_IGROUPR registers */ + add x1, x1, #0x80 /* GICD_IGROUPR */ + mov w0, #~0 /* All Group1 */ +1: str w0, [x1], #0x4 + sub w2, w2, #0x1 + cbnz w2, 1b + b 3f + + /* Slave initialize distributor */ +2: ldr x1, =GIC_DIST_BASE /* GICD_CTLR */ + mov w0, #~0 /* All Group1 */ + str w0, [x1, #0x80] + + /* Initialize cpu interface */ +3: ldr x1, =GIC_CPU_BASE /* GICC_CTLR */ + mov w0, #0x3 /* Enable Group0 & Group1 */ + str w0, [x1] + + mov w0, #0x1 << 7 /* Non-Secure access to GICC_PMR */ + str w0, [x1, #0x4] /* GICC_PMR */ + + /* Counter frequency initialization */ + ldr x0, =CONFIG_SYS_CNTFRQ + msr cntfrq_el0, x0 + + /* SCTLR_EL2 initialization */ + msr sctlr_el2, xzr + + /* Return to the EL2_SP2 mode from EL3 */ + mov x0, #0x3c9 /* EL2_SP2 | D | A | I | F */ + msr elr_el3, lr + msr spsr_el3, x0 + eret +ENDPROC(setup_el3) + +WEAK(setup_el2) + /* Initialize Generic Timers */ + mrs x0, cnthctl_el2 + orr x0, x0, #0x3 /* Enable EL1 access to timers */ + msr cnthctl_el2, x0 + msr cntvoff_el2, x0 /* Clear virtual offset */ + mrs x0, cntkctl_el1 + orr x0, x0, #0x3 /* EL0 access to counters */ + 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 CP15 traps to EL2 */ + + /* 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, #0x3c5 /* EL1_SP1 | D | A | I | F */ + msr elr_el2, lr + msr spsr_el2, x0 + eret +ENDPROC(setup_el2) + +WEAK(lowlevel_init) + 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. Using 512GB address range. + */ + ldr x0, =MEMORY_ATTRIBUTES + ldr x1, =TCR_FLAGS + + switch_el1_el2 x2, 1f, 2f, 3f +1: orr x1, x1, TCR_EL1_IPS_40BIT + msr mair_el1, x0 + msr tcr_el1, x1 + b 3f +2: orr x1, x1, TCR_EL2_IPS_40BIT + msr mair_el2, x0 + msr tcr_el2, x1 +3: +#endif + + /* Relocate vBAR */ + adr x0, vectors + switch_el1_el2 x1, 1f, 2f, 3f +1: msr vbar_el1, x0 + b 3f +2: msr vbar_el2, x0 +3: + + ret +ENDPROC(c_runtime_cpu_setup) diff --git a/arch/arm/cpu/armv8/timer.c b/arch/arm/cpu/armv8/timer.c new file mode 100644 index 0000000..9605e84 --- /dev/null +++ b/arch/arm/cpu/armv8/timer.c @@ -0,0 +1,80 @@ +/* + * (C) Copyright 2013 + * David Feng fenghua@phytium.com.cn + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <div64.h> +#include <linux/compiler.h> + +/* + * Genertic Timer implementation of __udelay/get_timer/get_ticks/get_tbclk + * functions. If any other timers used, another implementation should be + * placed in platform code. + */ + +static inline u64 get_cntfrq(void) +{ + u64 cntfrq; + asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq)); + return cntfrq; +} + +static inline u64 tick_to_time(u64 tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, get_cntfrq()); + return tick; +} + +static inline u64 time_to_tick(u64 time) +{ + time *= get_cntfrq(); + do_div(time, CONFIG_SYS_HZ); + return time; +} + +/* + * Generic timer implementation of get_tbclk() + */ +ulong __weak get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} + +/* + * Generic timer implementation of get_timer() + */ +ulong __weak get_timer(ulong base) +{ + u64 cval; + + isb(); + asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); + + return tick_to_time(cval) - base; +} + +/* + * Generic timer implementation of get_ticks() + */ +unsigned long long __weak get_ticks(void) +{ + return get_timer(0); +} + +/* + * Generic timer implementation of __udelay() + */ +void __weak __udelay(ulong usec) +{ + unsigned long ticks, limit; + + limit = get_ticks() + usec/1000; + + do { + ticks = get_ticks(); + } while (ticks < limit); +} diff --git a/arch/arm/cpu/armv8/tlb.S b/arch/arm/cpu/armv8/tlb.S new file mode 100644 index 0000000..6bb1e1f --- /dev/null +++ b/arch/arm/cpu/armv8/tlb.S @@ -0,0 +1,30 @@ +/* + * (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_el1_el2 x9, 1f, 2f, 3f +1: tlbi vmalle1 + dsb sy + isb + b 3f +2: tlbi alle2 + dsb sy + isb +3: + ret +ENDPROC(__asm_invalidate_tlb_all) diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds new file mode 100644 index 0000000..328d477 --- /dev/null +++ b/arch/arm/cpu/armv8/u-boot.lds @@ -0,0 +1,71 @@ +/* + * (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); + .reloc : { + __rel_got_start = .; + *(.got) + __rel_got_end = .; + } + + .image_copy_end : + { + *(.__image_copy_end) + } + + _end = .; + + . = ALIGN(8); + .bss : { + __bss_start = .; + *(.bss*) + . = ALIGN(8); + __bss_end = .; + } + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/arch/arm/include/asm/arch-armv8/gpio.h b/arch/arm/include/asm/arch-armv8/gpio.h new file mode 100644 index 0000000..afe7ece --- /dev/null +++ b/arch/arm/include/asm/arch-armv8/gpio.h @@ -0,0 +1,11 @@ +/* + * (C) Copyright 2013 + * David Feng fenghua@phytium.com.cn + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_ARMV8_GPIO_H_ +#define _ASM_ARMV8_GPIO_H_ + +#endif /* _ASM_ARMV8_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-armv8/mmu.h b/arch/arm/include/asm/arch-armv8/mmu.h new file mode 100644 index 0000000..33b3246 --- /dev/null +++ b/arch/arm/include/asm/arch-armv8/mmu.h @@ -0,0 +1,110 @@ +/* + * (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 (39) + +/* 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) | \ + (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_40BIT (2 << 32) +#define TCR_EL2_IPS_40BIT (2 << 16) + +/* 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_ */ diff --git a/arch/arm/include/asm/byteorder.h b/arch/arm/include/asm/byteorder.h index c3489f1..71a9966 100644 --- a/arch/arm/include/asm/byteorder.h +++ b/arch/arm/include/asm/byteorder.h @@ -23,10 +23,22 @@ # define __SWAB_64_THRU_32__ #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__ #include <linux/byteorder/big_endian.h> #else #include <linux/byteorder/little_endian.h> #endif
+#endif /* CONFIG_ARM64 */ + #endif diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index 6d60a4a..ddebbc8 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h @@ -11,6 +11,8 @@
#include <asm/system.h>
+#ifndef CONFIG_ARM64 + /* * 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 dram_bank_mmu_setup(int bank); + +#endif + /* * 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 diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h index 99b703e..0ee131d 100644 --- a/arch/arm/include/asm/config.h +++ b/arch/arm/include/asm/config.h @@ -9,4 +9,14 @@
#define CONFIG_LMB #define CONFIG_SYS_BOOT_RAMDISK_HIGH + +#ifdef CONFIG_ARM64 +/* + * Currently, GOT is used to relocate u-boot and + * configuration CONFIG_NEEDS_MANUAL_RELOC is needed. + */ +#define CONFIG_NEEDS_MANUAL_RELOC +#define CONFIG_PHYS_64BIT +#endif + #endif diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 79a9597..30a338e 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -47,6 +47,10 @@ struct arch_global_data {
#include <asm-generic/global_data.h>
-#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") +#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 ("r8") +#endif
#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1fbc531..6a1f05a 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.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_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; while(bytelen--) __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; while(wordlen--) __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; while(longlen--) __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; while(bytelen--) *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; while(wordlen--) *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; while(longlen--) diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index ff13f36..db8869e 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -54,5 +54,44 @@ bcs 1b .endm
+#ifdef CONFIG_ARM64 +/* + * Register aliases. + */ +lr .req x30 + +/* + * Branch according to exception level + */ +.macro switch_el1_el2, xreg, el1_label, el2_label, fail_label + mrs \xreg, CurrentEL + cmp \xreg, 0x4 + b.eq \el1_label + cmp \xreg, 0x8 + b.eq \el2_label + b \fail_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 + +#endif /* CONFIG_ARM64 */ + #endif /* __ASSEMBLY__ */ #endif /* __ASM_ARM_MACRO_H__ */ diff --git a/arch/arm/include/asm/posix_types.h b/arch/arm/include/asm/posix_types.h index c412486..9ba9add 100644 --- a/arch/arm/include/asm/posix_types.h +++ b/arch/arm/include/asm/posix_types.h @@ -13,6 +13,8 @@ #ifndef __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 * 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_uid_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 int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; +#endif /* CONFIG_ARM64 */ + typedef long __kernel_time_t; typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; diff --git a/arch/arm/include/asm/proc-armv/ptrace.h b/arch/arm/include/asm/proc-armv/ptrace.h index 79cc644..fd280cb 100644 --- a/arch/arm/include/asm/proc-armv/ptrace.h +++ b/arch/arm/include/asm/proc-armv/ptrace.h @@ -12,6 +12,25 @@
#include <linux/config.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 FIQ26_MODE 0x01 #define IRQ26_MODE 0x02 @@ -106,4 +125,6 @@ static inline int valid_user_regs(struct pt_regs *regs)
#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_ARM64 */ + #endif diff --git a/arch/arm/include/asm/proc-armv/system.h b/arch/arm/include/asm/proc-armv/system.h index b4cfa68..19b2b44 100644 --- a/arch/arm/include/asm/proc-armv/system.h +++ b/arch/arm/include/asm/proc-armv/system.h @@ -15,6 +15,60 @@ /* * 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) \ ({ \ unsigned long temp; \ @@ -109,7 +163,10 @@ : "r" (x) \ : "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 * cache totally. This means that the cache becomes inconsistent, and, diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 760345f..e79f790 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -1,6 +1,79 @@ #ifndef __ASM_ARM_SYSTEM_H #define __ASM_ARM_SYSTEM_H
+#ifdef CONFIG_ARM64 + +/* + * SCTLR_EL2 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 curent_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 = curent_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 + panic("Not Supported Exception Level"); + + return val; +} + +static inline void set_sctlr(unsigned int val) +{ + unsigned int el; + + el = curent_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 + panic("Not Supported Exception Level"); + + 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); + +#endif /* __ASSEMBLY__ */ + +#else /* CONFIG_ARM64 */ + #ifdef __KERNEL__
#define CPU_ARCH_UNKNOWN 0 @@ -45,6 +118,8 @@ #define CR_AFE (1 << 29) /* Access flag 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 * asked it for some inline assembly sequences. Apparently we can't trust @@ -132,4 +207,6 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop);
#endif /* __KERNEL__ */
+#endif /* CONFIG_ARM64 */ + #endif diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h index 71dc049..2326420 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/asm/types.h @@ -39,7 +39,11 @@ typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64;
+#ifdef CONFIG_ARM64 +#define BITS_PER_LONG 64 +#else /* CONFIG_ARM64 */ #define BITS_PER_LONG 32 +#endif /* CONFIG_ARM64 */
/* Dma addresses are 32-bits wide. */
diff --git a/arch/arm/include/asm/u-boot.h b/arch/arm/include/asm/u-boot.h index 2b5fce8..cb81232 100644 --- a/arch/arm/include/asm/u-boot.h +++ b/arch/arm/include/asm/u-boot.h @@ -44,6 +44,10 @@ typedef struct bd_info { #endif /* !CONFIG_SYS_GENERIC_BOARD */
/* For image.h:image_check_target_arch() */ +#ifndef CONFIG_ARM64 #define IH_ARCH_DEFAULT IH_ARCH_ARM +#else +#define IH_ARCH_DEFAULT IH_ARCH_ARM64 +#endif
#endif /* _U_BOOT_H_ */ diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h index 44593a8..0a228fb 100644 --- a/arch/arm/include/asm/unaligned.h +++ b/arch/arm/include/asm/unaligned.h @@ -8,7 +8,7 @@ /* * Select endianness */ -#ifndef __ARMEB__ +#if __BYTE_ORDER == __LITTLE_ENDIAN #define get_unaligned __get_unaligned_le #define put_unaligned __put_unaligned_le #else diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 4e78723..03c31c7 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -10,6 +10,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).o LIBGCC = $(obj)libgcc.o
+ifdef CONFIG_ARM64 +SOBJS-y += crt0_64.o +else GLSOBJS += _ashldi3.o GLSOBJS += _ashrdi3.o GLSOBJS += _divsi3.o @@ -21,9 +24,14 @@ GLSOBJS += _umodsi3.o GLCOBJS += div0.o
SOBJS-y += crt0.o +endif
ifndef CONFIG_SPL_BUILD +ifdef CONFIG_ARM64 +SOBJS-y += relocate_64.o +else SOBJS-y += relocate.o +endif ifndef CONFIG_SYS_GENERIC_BOARD COBJS-y += board.o endif @@ -38,11 +46,17 @@ else COBJS-$(CONFIG_SPL_FRAMEWORK) += spl.o endif
+ifdef CONFIG_ARM64 +COBJS-y += interrupts_64.o +else COBJS-y += interrupts.o +endif COBJS-y += reset.o
COBJS-y += cache.o +ifndef CONFIG_ARM64 COBJS-y += cache-cp15.o +endif
SRCS := $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \ $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 34f50b0..d6d0833 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -344,7 +344,7 @@ void board_init_f(ulong bootflag)
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) /* reserve TLB table */ - gd->arch.tlb_size = 4096 * 4; + gd->arch.tlb_size = PGTABLE_SIZE; addr -= gd->arch.tlb_size;
/* round down to next 64 kB limit */ @@ -419,6 +419,7 @@ void board_init_f(ulong bootflag) } #endif
+#ifndef CONFIG_ARM64 /* setup stackpointer for exeptions */ gd->irq_sp = addr_sp; #ifdef CONFIG_USE_IRQ @@ -431,6 +432,10 @@ void board_init_f(ulong bootflag)
/* 8-byte alignment for ABI compliance */ addr_sp &= ~0x07; +#else /* CONFIG_ARM64 */ + /* 16-byte alignment for ABI compliance */ + addr_sp &= ~0x0f; +#endif /* CONFIG_ARM64 */ #else addr_sp += 128; /* leave 32 words for abort-stack */ gd->irq_sp = addr_sp; @@ -513,7 +518,15 @@ void board_init_r(gd_t *id, ulong dest_addr) ulong flash_size; #endif
+ /* + * Relocate routines of serial_device first so that + * printf access the correct puts function. This is critical + * when CONFIG_NEEDS_MANUAL_RELOC is needed. + */ + serial_initialize(); + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
monitor_flash_len = _end_ofs; @@ -523,6 +536,15 @@ void board_init_r(gd_t *id, ulong dest_addr)
debug("monitor flash len: %08lX\n", monitor_flash_len); board_init(); /* Setup chipselects */ + +#ifdef CONFIG_NEEDS_MANUAL_RELOC + /* + * We have to relocate the command table manually + */ + fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd), + ll_entry_count(cmd_tbl_t, cmd)); +#endif /* CONFIG_NEEDS_MANUAL_RELOC */ + /* * TODO: printing of the clock inforamtion of the board is now * implemented as part of bdinfo command. Currently only support for @@ -532,7 +554,6 @@ void board_init_r(gd_t *id, ulong dest_addr) #ifdef CONFIG_CLOCKS set_cpu_clk_info(); /* Setup clock information */ #endif - serial_initialize();
debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index eefb456..26e85f0 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -222,6 +222,21 @@ static void boot_prep_linux(bootm_headers_t *images) /* Subcommand: GO */ 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; char *s; void (*kernel_entry)(int zero, int arch, uint params); @@ -248,6 +263,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
if (!fake) kernel_entry(0, machid, r2); +#endif }
/* Main Entry point for arm bootm implementation diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S new file mode 100644 index 0000000..ddd46eb --- /dev/null +++ b/arch/arm/lib/crt0_64.S @@ -0,0 +1,116 @@ +/* + * 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 x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */ + ldr x0, =__bss_start + add x0, x0, x9 /* x0 <- __bss_start in RAM */ + ldr x1, =__bss_end + add x1, x1, x9 /* x1 <- __bss_end in RAM */ + 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) diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c new file mode 100644 index 0000000..b476722 --- /dev/null +++ b/arch/arm/lib/interrupts_64.c @@ -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"); +} diff --git a/arch/arm/lib/relocate_64.S b/arch/arm/lib/relocate_64.S new file mode 100644 index 0000000..29c3239 --- /dev/null +++ b/arch/arm/lib/relocate_64.S @@ -0,0 +1,57 @@ +/* + * 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. + * + * NOTE: + * GOT is used and configuration CONFIG_NEEDS_MANUAL_RELOC is needed. + */ +ENTRY(relocate_code) + /* + * Copy u-boot from flash to RAM + */ + ldr x1, =__image_copy_start /* x1 <- copy source */ + cmp x1, x0 + b.eq relocate_done /* skip relocation */ + mov x2, x0 /* x2 <- copy destination */ + ldr x3, =__image_copy_end /* x3 <- source end address */ + +copy_loop: + ldp x10, x11, [x1], #16 /* copy from source address [x1] */ + stp x10, x11, [x2], #16 /* copy to target address [x2] */ + cmp x1, x3 /* until source end address [x3] */ + b.lo copy_loop + + /* + * Fix .reloc relocations + */ + ldr x9, [x18, #GD_RELOC_OFF]/* x9 <- relocation offset */ + ldr x1, =__rel_got_start /* x1 <- rel got start ofs */ + add x1, x1, x9 /* x1 <- rel got start in RAM */ + ldr x2, =__rel_got_end /* x2 <- rel got end ofs */ + add x2, x2, x9 /* x2 <- rel got end in RAM */ +fixloop: + ldr x10, [x1] + add x10, x10, x9 /* x10 <- address to be fixed up */ + str x10, [x1] + add x1, x1, #8 /* each got entry is 8 bytes */ + cmp x1, x2 + b.lo fixloop + +relocate_done: + ret +ENDPROC(relocate_code) diff --git a/common/image.c b/common/image.c index b0ae58f..4145354 100644 --- a/common/image.c +++ b/common/image.c @@ -81,6 +81,7 @@ static const table_entry_t uimage_arch[] = { { IH_ARCH_NDS32, "nds32", "NDS32", }, { IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",}, { IH_ARCH_SANDBOX, "sandbox", "Sandbox", }, + { IH_ARCH_ARM64, "arm64", "AArch64", }, { -1, "", "", }, };
diff --git a/doc/README.arm64 b/doc/README.arm64 new file mode 100644 index 0000000..746ce6a --- /dev/null +++ b/doc/README.arm64 @@ -0,0 +1,33 @@ +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 could be running at EL1 or EL2. + +2. Currenly, U-boot for arm64 is compiled with AArch64-gcc. AArch64-gcc + use rela relocation format, it cannot be relocated during running. So, + GOT is used to relocate u-boot and CONFIG_NEEDS_MANUAL_RELOC is needed. + +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. Generic board is supported. + +5. 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 + Simon Glass sjg@chromium.org + Sharma Bhupesh bhupesh.sharma@freescale.com + Rob Herring robherring2@gmail.com diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c index 8fb1765..fc5d7ef 100644 --- a/examples/standalone/stubs.c +++ b/examples/standalone/stubs.c @@ -39,6 +39,20 @@ gd_t *global_data; " bctr\n" \ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11"); #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 /* * r8 holds the pointer to the global_data, ip is a call-clobbered * register @@ -50,6 +64,7 @@ gd_t *global_data; " ldr ip, [r8, %0]\n" \ " ldr pc, [ip, %1]\n" \ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip"); +#endif #elif defined(CONFIG_MIPS) /* * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call- diff --git a/include/image.h b/include/image.h index ee6eb8d..7de2bb2 100644 --- a/include/image.h +++ b/include/image.h @@ -156,6 +156,7 @@ struct lmb; #define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */ #define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */ #define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */ +#define IH_ARCH_ARM64 22 /* ARM64 */
/* * Image Types

From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn Signed-off-by: Bhupesh Sharma bhupesh.sharma@freescale.com --- board/armltd/dts/vexpress64.dts | 439 ++++++++++++++++++++++++++++++++++ board/armltd/vexpress64/Makefile | 27 +++ board/armltd/vexpress64/vexpress64.c | 70 ++++++ boards.cfg | 1 + include/configs/vexpress_aemv8a.h | 191 +++++++++++++++ 5 files changed, 728 insertions(+) create mode 100644 board/armltd/dts/vexpress64.dts create mode 100644 board/armltd/vexpress64/Makefile create mode 100644 board/armltd/vexpress64/vexpress64.c create mode 100644 include/configs/vexpress_aemv8a.h
diff --git a/board/armltd/dts/vexpress64.dts b/board/armltd/dts/vexpress64.dts new file mode 100644 index 0000000..067fea7 --- /dev/null +++ b/board/armltd/dts/vexpress64.dts @@ -0,0 +1,439 @@ +/* + * ARM Ltd. Fast Models + * + * Architecture Envelope Model (AEM) ARMv8-A + * ARMAEMv8AMPCT + * + * RTSM_VE_AEMv8A.lisa + */ + +/dts-v1/; + +/memreserve/ 0x80000000 0x00010000; + +/ { + /* boot configurations for u-boot */ + config { + /*bootdelay = <1>;*/ + kernel-offset = <0x100000>; + rootdisk-offset = <0x800000>; + bootcmd = "bootm 0x100000 0x800000:0x2000000"; + }; +}; + +/ { + model = "RTSM_VE_AEMv8A"; + compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + /* chosen */ + /* generated by u-boot */ + + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <1>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <2>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <3>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x80000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2c001000 0 0x1000>, + <0x0 0x2c002000 0 0x1000>, + <0x0 0x2c004000 0 0x2000>, + <0x0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xff01>, + <1 14 0xff01>, + <1 11 0xff01>, + <1 10 0xff01>; + clock-frequency = <100000000>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 6 &gic 0 6 4>, + <0 0 7 &gic 0 7 4>, + <0 0 8 &gic 0 8 4>, + <0 0 9 &gic 0 9 4>, + <0 0 10 &gic 0 10 4>, + <0 0 11 &gic 0 11 4>, + <0 0 12 &gic 0 12 4>, + <0 0 13 &gic 0 13 4>, + <0 0 14 &gic 0 14 4>, + <0 0 15 &gic 0 15 4>, + <0 0 16 &gic 0 16 4>, + <0 0 17 &gic 0 17 4>, + <0 0 18 &gic 0 18 4>, + <0 0 19 &gic 0 19 4>, + <0 0 20 &gic 0 20 4>, + <0 0 21 &gic 0 21 4>, + <0 0 22 &gic 0 22 4>, + <0 0 23 &gic 0 23 4>, + <0 0 24 &gic 0 24 4>, + <0 0 25 &gic 0 25 4>, + <0 0 26 &gic 0 26 4>, + <0 0 27 &gic 0 27 4>, + <0 0 28 &gic 0 28 4>, + <0 0 29 &gic 0 29 4>, + <0 0 30 &gic 0 30 4>, + <0 0 31 &gic 0 31 4>, + <0 0 32 &gic 0 32 4>, + <0 0 33 &gic 0 33 4>, + <0 0 34 &gic 0 34 4>, + <0 0 35 &gic 0 35 4>, + <0 0 36 &gic 0 36 4>, + <0 0 37 &gic 0 37 4>, + <0 0 38 &gic 0 38 4>, + <0 0 39 &gic 0 39 4>, + <0 0 40 &gic 0 40 4>, + <0 0 41 &gic 0 41 4>, + <0 0 42 &gic 0 42 4>; + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + #interrupt-cells = <1>; + ranges; + + flash@0,00000000 { + compatible = "arm,vexpress-flash", "cfi-flash"; + reg = <0 0x00000000 0x04000000>, + <4 0x00000000 0x04000000>; + bank-width = <4>; + }; + + vram@2,00000000 { + compatible = "arm,vexpress-vram"; + reg = <2 0x00000000 0x00800000>; + }; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <15>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@010000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@020000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + aaci@040000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x040000 0x1000>; + interrupts = <11>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + mmci@050000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x050000 0x1000>; + interrupts = <9 10>; + cd-gpios = <&v2m_sysreg 0 0>; + wp-gpios = <&v2m_sysreg 1 0>; + max-frequency = <12000000>; + vmmc-supply = <&v2m_fixed_3v3>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + kmi@060000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x060000 0x1000>; + interrupts = <12>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@070000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x070000 0x1000>; + interrupts = <13>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + v2m_serial0: uart@090000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <5>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@0a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <6>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@0b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <7>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@0c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <8>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@0f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <2>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <3>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + clcd@1f0000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x1f0000 0x1000>; + interrupts = <14>; + clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; + clock-names = "clcdclk", "apb_pclk"; + }; + }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + v2m_oscclk1: osc@1 { + /* CLCD clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <23750000 63500000>; + #clock-cells = <0>; + clock-output-names = "v2m:oscclk1"; + }; + + reset@0 { + compatible = "arm,vexpress-reset"; + arm,vexpress-sysreg,func = <5 0>; + }; + + muxfpga@0 { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + shutdown@0 { + compatible = "arm,vexpress-shutdown"; + arm,vexpress-sysreg,func = <8 0>; + }; + + reboot@0 { + compatible = "arm,vexpress-reboot"; + arm,vexpress-sysreg,func = <9 0>; + }; + + dvimode@0 { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "VGA"; + refresh = <60>; + xres = <640>; + yres = <480>; + pixclock = <39721>; + left_margin = <40>; + right_margin = <24>; + upper_margin = <32>; + lower_margin = <11>; + hsync_len = <96>; + vsync_len = <2>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + + panel@1 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/board/armltd/vexpress64/Makefile b/board/armltd/vexpress64/Makefile new file mode 100644 index 0000000..f907c92 --- /dev/null +++ b/board/armltd/vexpress64/Makefile @@ -0,0 +1,27 @@ +# +# (C) Copyright 2000-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).o + +COBJS := vexpress64.o + +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c new file mode 100644 index 0000000..0feb604 --- /dev/null +++ b/board/armltd/vexpress64/vexpress64.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2013 + * David Feng fenghua@phytium.com.cn + * Sharma Bhupesh B45370@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <malloc.h> +#include <errno.h> +#include <netdev.h> +#include <asm/io.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + return 0; +} + +int dram_init(void) +{ + gd->ram_size = PHYS_SDRAM_1_SIZE; + return 0; +} + +int timer_init(void) +{ + return 0; +} + +/* + * Board specific reset that is system reset. + */ +void reset_cpu(ulong addr) +{ +} + +/* + * Default implementation of gpio related functiuons + * Real implementation should be in gpio driver. + * fdtdec.c need this function, but currenty no gpio driver defined + */ +int __weak gpio_get_value(unsigned gpio) +{ + return 0; +} + +void __weak gpio_set_value(unsigned gpio, int vlaue) +{ + return; +} + +void __weak gpio_request(unsigned gpio, const char *label) +{ + return; +} + +/* + * Board specific ethernet initialization routine. + */ +int board_eth_init(bd_t *bis) +{ + int rc = 0; +#ifdef CONFIG_SMC91111 + rc = smc91111_initialize(0, CONFIG_SMC91111_BASE); +#endif + return rc; +} diff --git a/boards.cfg b/boards.cfg index 9fc77fb..d66bd46 100644 --- a/boards.cfg +++ b/boards.cfg @@ -380,6 +380,7 @@ Active arm pxa - - vpac270 Active arm pxa - icpdas lp8x4x lp8x4x - Sergey Yanovich ynvich@gmail.com Active arm pxa - toradex - colibri_pxa270 - Marek Vasut marek.vasut@gmail.com Active arm sa1100 - - - jornada - Kristoffer Ericson kristoffer.ericson@gmail.com +Active arm armv8 - armltd vexpress64 vexpress_aemv8a vexpress_aemv8a:ARM64 David Feng fenghua@phytium.com.cn Active avr32 at32ap at32ap700x atmel - atngw100 - Haavard Skinnemoen haavard.skinnemoen@atmel.com Active avr32 at32ap at32ap700x atmel - atngw100mkii - Andreas Bießmann andreas.devel@googlemail.com Active avr32 at32ap at32ap700x atmel atstk1000 atstk1002 - Haavard Skinnemoen haavard.skinnemoen@atmel.com diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h new file mode 100644 index 0000000..01c95f5 --- /dev/null +++ b/include/configs/vexpress_aemv8a.h @@ -0,0 +1,191 @@ +/* + * Configuration for Versatile Express. Parts were derived from other ARM + * configurations. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __VEXPRESS_AEMV8A_H +#define __VEXPRESS_AEMV8A_H + +#define DEBUG + +/*#define CONFIG_BOOTING_EL1*/ + +/*#define CONFIG_SYS_GENERIC_BOARD*/ + +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_SUPPORT_RAW_INITRD + +/* Cache Definitions */ +#define CONFIG_SYS_DCACHE_OFF +#define CONFIG_SYS_ICACHE_OFF + +#define CONFIG_IDENT_STRING " vexpress_aemv8a" +#define CONFIG_BOOTP_VCI_STRING "U-boot.armv8.vexpress_aemv8a" + +/* Link Definitions */ +#define CONFIG_SYS_TEXT_BASE 0x80000000 +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x400000) + +/* Flat Device Tree Definitions */ +#define CONFIG_OF_EMBED +#define CONFIG_OF_CONTROL +#define CONFIG_OF_LIBFDT + +#define CONFIG_DEFAULT_DEVICE_TREE vexpress64 + +/* SMP Definitions */ +#define SECONDARY_CPU_MAILBOX 0x8000fff8 + +/* CS register bases for the original memory map. */ +#define V2M_PA_CS0 0x00000000 +#define V2M_PA_CS1 0x14000000 +#define V2M_PA_CS2 0x18000000 +#define V2M_PA_CS3 0x1c000000 +#define V2M_PA_CS4 0x0c000000 +#define V2M_PA_CS5 0x10000000 + +#define V2M_PERIPH_OFFSET(x) (x << 16) +#define V2M_SYSREGS (V2M_PA_CS3 + V2M_PERIPH_OFFSET(1)) +#define V2M_SYSCTL (V2M_PA_CS3 + V2M_PERIPH_OFFSET(2)) +#define V2M_SERIAL_BUS_PCI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(3)) + +#define V2M_BASE 0x80000000 + +/* + * Physical addresses, offset from V2M_PA_CS0-3 + */ +#define V2M_NOR0 (V2M_PA_CS0) +#define V2M_NOR1 (V2M_PA_CS4) +#define V2M_SRAM (V2M_PA_CS1) + +/* Common peripherals relative to CS7. */ +#define V2M_AACI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(4)) +#define V2M_MMCI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(5)) +#define V2M_KMI0 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(6)) +#define V2M_KMI1 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(7)) + +#define V2M_UART0 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(9)) +#define V2M_UART1 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(10)) +#define V2M_UART2 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(11)) +#define V2M_UART3 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(12)) + +#define V2M_WDT (V2M_PA_CS3 + V2M_PERIPH_OFFSET(15)) + +#define V2M_TIMER01 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(17)) +#define V2M_TIMER23 (V2M_PA_CS3 + V2M_PERIPH_OFFSET(18)) + +#define V2M_SERIAL_BUS_DVI (V2M_PA_CS3 + V2M_PERIPH_OFFSET(22)) +#define V2M_RTC (V2M_PA_CS3 + V2M_PERIPH_OFFSET(23)) + +#define V2M_CF (V2M_PA_CS3 + V2M_PERIPH_OFFSET(26)) + +#define V2M_CLCD (V2M_PA_CS3 + V2M_PERIPH_OFFSET(31)) + +/* System register offsets. */ +#define V2M_SYS_CFGDATA (V2M_SYSREGS + 0x0a0) +#define V2M_SYS_CFGCTRL (V2M_SYSREGS + 0x0a4) +#define V2M_SYS_CFGSTAT (V2M_SYSREGS + 0x0a8) + +/* Generic Timer Definitions */ +#define CONFIG_SYS_CNTFRQ (0x1800000) /* 24MHz */ + +/* Generic Interrupt Controller Definitions */ +#define GIC_DIST_BASE (0x2C001000) +#define GIC_CPU_BASE (0x2C002000) + +#define CONFIG_SYS_MEMTEST_START V2M_BASE +#define CONFIG_SYS_MEMTEST_END (V2M_BASE + 0x80000000) + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024) + +/* SMSC9115 Ethernet from SMSC9118 family */ +#define CONFIG_SMC9111 1 +#define CONFIG_SMC9111_BASE (0x1a000000) + +/* PL011 Serial Configuration */ +#define CONFIG_PL011_SERIAL +#define CONFIG_PL011_CLOCK 24000000 +#define CONFIG_PL01x_PORTS {(void *)CONFIG_SYS_SERIAL0, \ + (void *)CONFIG_SYS_SERIAL1} +#define CONFIG_CONS_INDEX 0 + +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } +#define CONFIG_SYS_SERIAL0 V2M_UART0 +#define CONFIG_SYS_SERIAL1 V2M_UART1 + +/* Command line configuration */ +#define CONFIG_MENU +/*#define CONFIG_MENU_SHOW*/ +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_BDI +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_PXE +#define CONFIG_CMD_ENV +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_IMI +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET +#define CONFIG_CMD_PING +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_RUN +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_ECHO +#define CONFIG_CMD_SOURCE +#define CONFIG_CMD_FAT +#define CONFIG_DOS_PARTITION + +/* BOOTP options */ +#define CONFIG_BOOTP_BOOTFILESIZE +#define CONFIG_BOOTP_BOOTPATH +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_BOOTP_HOSTNAME +#define CONFIG_BOOTP_PXE +#define CONFIG_BOOTP_PXE_CLIENTARCH 0x100 + +/* Miscellaneous configurable options */ +#define CONFIG_SYS_LOAD_ADDR (V2M_BASE + 0x10000000) + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM_1 (V2M_BASE) /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE 0x80000000 /* 2048 MB */ +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 + +#define CONFIG_SYS_HZ 1000 + +/* Initial environment variables */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "loadaddr=0x80100000\0" \ + "kernel_addr=0x100000\0" \ + "ramdisk_addr=0x800000\0" \ + "ramdisk_size=0x2000000\0" \ + "fdt_high=0xa0000000\0" \ + "console=ttyAMA0,38400n8\0" + +#define CONFIG_BOOTARGS "console=ttyAMA0 root=/dev/ram0" +#define CONFIG_BOOTCOMMAND "bootm $kernel_addr $ramdisk_addr:$ramdisk_size" +#define CONFIG_BOOTDELAY -1 + +/* Store environment at top of flash */ +#define CONFIG_ENV_IS_NOWHERE 1 +#define CONFIG_ENV_SIZE 0x1000 + +/* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PROMPT "VExpress# " +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot args buffer */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_CMDLINE_EDITING 1 +#define CONFIG_SYS_MAXARGS 64 /* max command args */ + +#endif /* __VEXPRESS_AEMV8A_H */

From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn --- common/board_f.c | 18 +++++++++++------- common/board_r.c | 20 +++++++++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c index 0ada1af..5891ad2 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -458,7 +458,7 @@ static int reserve_round_4k(void) static int reserve_mmu(void) { /* reserve TLB table */ - gd->arch.tlb_size = 4096 * 4; + gd->arch.tlb_size = PGTABLE_SIZE; gd->relocaddr -= gd->arch.tlb_size;
/* round down to next 64 kB limit */ @@ -610,7 +610,7 @@ static int reserve_stacks(void) * TODO(sjg@chromium.org): Perhaps create arch_reserve_stack() * to handle this and put in arch/xxx/lib/stack.c */ -# ifdef CONFIG_ARM +# if defined(CONFIG_ARM) && !defined(CONFIG_ARM64) # ifdef CONFIG_USE_IRQ gd->start_addr_sp -= (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ); debug("Reserving %zu Bytes for IRQ stack at: %08lx\n", @@ -807,11 +807,6 @@ static int mark_bootstage(void) }
static init_fnc_t init_sequence_f[] = { -#if !defined(CONFIG_CPM2) && !defined(CONFIG_MPC512X) && \ - !defined(CONFIG_MPC83xx) && !defined(CONFIG_MPC85xx) && \ - !defined(CONFIG_MPC86xx) && !defined(CONFIG_X86) - zero_global_data, -#endif #ifdef CONFIG_SANDBOX setup_ram_buf, #endif @@ -1005,6 +1000,15 @@ void board_init_f(ulong boot_flags) gd = &data; #endif
+ /* + * Zero gd_t first, otherwise the debug print(if DEBUG defined) + * in initcall_run_list function before zero_global_data is called + * will go wrong. + */ +#ifndef CONFIG_X86 + zero_global_data(); +#endif + gd->flags = boot_flags;
if (initcall_run_list(init_sequence_f)) diff --git a/common/board_r.c b/common/board_r.c index 86ca1cb..8984cf3 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -157,6 +157,13 @@ static int initr_reloc_global_data(void) */ gd->env_addr += gd->relocaddr - CONFIG_SYS_MONITOR_BASE; #endif +#ifdef CONFIG_NEEDS_MANUAL_RELOC + /* + * We have to relocate the command table manually + */ + fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd), + ll_entry_count(cmd_tbl_t, cmd)); +#endif /* CONFIG_NEEDS_MANUAL_RELOC */ return 0; }
@@ -705,6 +712,7 @@ static int run_main_loop(void) * TODO: perhaps reset the watchdog in the initcall function after each call? */ init_fnc_t init_sequence_r[] = { + initr_serial, initr_trace, initr_reloc, /* TODO: could x86/PPC have this also perhaps? */ @@ -722,7 +730,6 @@ init_fnc_t init_sequence_r[] = { set_cpu_clk_info, /* Setup clock information */ #endif initr_reloc_global_data, - initr_serial, initr_announce, INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_PPC @@ -899,6 +906,7 @@ init_fnc_t init_sequence_r[] = { initr_modem, #endif run_main_loop, + NULL, };
void board_init_r(gd_t *new_gd, ulong dest_addr) @@ -906,6 +914,16 @@ void board_init_r(gd_t *new_gd, ulong dest_addr) #ifndef CONFIG_X86 gd = new_gd; #endif +#ifdef CONFIG_NEEDS_MANUAL_RELOC + /* + * We have to relocate the init_sequence_r table manually + */ + init_fnc_t *init_fnc_ptr; + for (init_fnc_ptr = init_sequence_r; *init_fnc_ptr; ++init_fnc_ptr) + *(unsigned long *)init_fnc_ptr = + (unsigned long)(*init_fnc_ptr) + gd->reloc_off; +#endif /* CONFIG_NEEDS_MANUAL_RELOC */ + if (initcall_run_list(init_sequence_r)) hang();

From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn --- common/fdt_support.c | 66 ++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 32 deletions(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index b034c98..9bc5821 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -21,6 +21,34 @@ */ DECLARE_GLOBAL_DATA_PTR;
+/* + * Get cells len in bytes + * if #NNNN-cells property is 2 then len is 8 + * otherwise len is 4 + */ +static int get_cells_len(void *blob, char *nr_cells_name) +{ + const fdt32_t *cell; + + cell = fdt_getprop(blob, 0, nr_cells_name, NULL); + if (cell && fdt32_to_cpu(*cell) == 2) + return 8; + + return 4; +} + +/* + * Write a 4 or 8 byte big endian cell + */ +static void write_cell(u8 *addr, u64 val, int size) +{ + int shift = (size - 1) * 8; + while (size-- > 0) { + *addr++ = (val >> shift) & 0xff; + shift -= 8; + } +} + /** * fdt_getprop_u32_default - Find a node and return it's property or a default * @@ -131,9 +159,9 @@ static int fdt_fixup_stdout(void *fdt, int chosenoff)
int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force) { - int nodeoffset; + int nodeoffset, addr_cell_len; int err, j, total; - fdt32_t tmp; + fdt64_t tmp; const char *path; uint64_t addr, size;
@@ -170,9 +198,11 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force) return err; }
+ addr_cell_len = get_cells_len(fdt, "#address-cells"); + path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL); if ((path == NULL) || force) { - tmp = cpu_to_fdt32(initrd_start); + write_cell((u8 *)&tmp, initrd_start, addr_cell_len); err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp)); if (err < 0) { @@ -181,7 +211,7 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force) fdt_strerror(err)); return err; } - tmp = cpu_to_fdt32(initrd_end); + write_cell((u8 *)&tmp, initrd_end, addr_cell_len); err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp)); if (err < 0) { @@ -343,34 +373,6 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); }
-/* - * Get cells len in bytes - * if #NNNN-cells property is 2 then len is 8 - * otherwise len is 4 - */ -static int get_cells_len(void *blob, char *nr_cells_name) -{ - const fdt32_t *cell; - - cell = fdt_getprop(blob, 0, nr_cells_name, NULL); - if (cell && fdt32_to_cpu(*cell) == 2) - return 8; - - return 4; -} - -/* - * Write a 4 or 8 byte big endian cell - */ -static void write_cell(u8 *addr, u64 val, int size) -{ - int shift = (size - 1) * 8; - while (size-- > 0) { - *addr++ = (val >> shift) & 0xff; - shift -= 8; - } -} - #ifdef CONFIG_NR_DRAM_BANKS #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS #else

From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn --- common/cmd_pxe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index a2fb50a..df58522 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -57,7 +57,7 @@ static int format_mac_pxe(char *outbuf, size_t outbuf_len) uchar ethaddr[6];
if (outbuf_len < 21) { - printf("outbuf is too small (%d < 21)\n", outbuf_len); + printf("outbuf is too small (%zd < 21)\n", outbuf_len);
return -EINVAL; } @@ -100,7 +100,7 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path, path_len = (last_slash - bootfile) + 1;
if (bootfile_path_size < path_len) { - printf("bootfile_path too small. (%d < %d)\n", + printf("bootfile_path too small. (%zd < %zd)\n", bootfile_path_size, path_len);
return -1;

From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn --- include/linux/linkage.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 9ddf830..2a2848a 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -49,6 +49,10 @@ .globl SYMBOL_NAME(name); \ LENTRY(name)
+#define WEAK(name) \ + .weak SYMBOL_NAME(name); \ + LENTRY(name) + #ifndef END #define END(name) \ .size name, .-name

On 09/26/2013 08:35 AM, fenghua@phytium.com.cn wrote:
From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn
include/linux/linkage.h | 4 ++++ 1 file changed, 4 insertions(+)
This patch should come before adding core v8 support.
Rob
diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 9ddf830..2a2848a 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -49,6 +49,10 @@ .globl SYMBOL_NAME(name); \ LENTRY(name)
+#define WEAK(name) \
- .weak SYMBOL_NAME(name); \
- LENTRY(name)
#ifndef END #define END(name) \ .size name, .-name

On 09/26/2013 08:35 AM, fenghua@phytium.com.cn wrote:
From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn
arch/arm/config.mk | 4 +
FYI, some recent mainline changes to config.mk break the build for me.
arch/arm/cpu/armv8/Makefile | 38 +++++ arch/arm/cpu/armv8/cache.S | 130 +++++++++++++++++ arch/arm/cpu/armv8/cache_v8.c | 218 ++++++++++++++++++++++++++++ arch/arm/cpu/armv8/config.mk | 16 +++ arch/arm/cpu/armv8/cpu.c | 67 +++++++++ arch/arm/cpu/armv8/exceptions.S | 115 +++++++++++++++ arch/arm/cpu/armv8/start.S | 234 +++++++++++++++++++++++++++++++ arch/arm/cpu/armv8/timer.c | 80 +++++++++++ arch/arm/cpu/armv8/tlb.S | 30 ++++ arch/arm/cpu/armv8/u-boot.lds | 71 ++++++++++ arch/arm/include/asm/arch-armv8/gpio.h | 11 ++ arch/arm/include/asm/arch-armv8/mmu.h | 110 +++++++++++++++ arch/arm/include/asm/byteorder.h | 12 ++ arch/arm/include/asm/cache.h | 5 + arch/arm/include/asm/config.h | 10 ++ arch/arm/include/asm/global_data.h | 6 +- arch/arm/include/asm/io.h | 15 +- arch/arm/include/asm/macro.h | 39 ++++++ arch/arm/include/asm/posix_types.h | 10 ++ arch/arm/include/asm/proc-armv/ptrace.h | 21 +++ arch/arm/include/asm/proc-armv/system.h | 59 +++++++- arch/arm/include/asm/system.h | 77 ++++++++++ arch/arm/include/asm/types.h | 4 + arch/arm/include/asm/u-boot.h | 4 + arch/arm/include/asm/unaligned.h | 2 +- arch/arm/lib/Makefile | 14 ++ arch/arm/lib/board.c | 25 +++- arch/arm/lib/bootm.c | 16 +++ arch/arm/lib/crt0_64.S | 116 +++++++++++++++ arch/arm/lib/interrupts_64.c | 120 ++++++++++++++++ arch/arm/lib/relocate_64.S | 57 ++++++++ common/image.c | 1 + doc/README.arm64 | 33 +++++ examples/standalone/stubs.c | 15 ++ include/image.h | 1 + 36 files changed, 1775 insertions(+), 11 deletions(-) create mode 100644 arch/arm/cpu/armv8/Makefile create mode 100644 arch/arm/cpu/armv8/cache.S create mode 100644 arch/arm/cpu/armv8/cache_v8.c create mode 100644 arch/arm/cpu/armv8/config.mk create mode 100644 arch/arm/cpu/armv8/cpu.c create mode 100644 arch/arm/cpu/armv8/exceptions.S create mode 100644 arch/arm/cpu/armv8/start.S create mode 100644 arch/arm/cpu/armv8/timer.c create mode 100644 arch/arm/cpu/armv8/tlb.S create mode 100644 arch/arm/cpu/armv8/u-boot.lds create mode 100644 arch/arm/include/asm/arch-armv8/gpio.h create mode 100644 arch/arm/include/asm/arch-armv8/mmu.h create mode 100644 arch/arm/lib/crt0_64.S create mode 100644 arch/arm/lib/interrupts_64.c create mode 100644 arch/arm/lib/relocate_64.S create mode 100644 doc/README.arm64
diff --git a/arch/arm/config.mk b/arch/arm/config.mk index ce3903b..95c07ad 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -74,7 +74,9 @@ endif endif
# needed for relocation +ifndef CONFIG_ARM64 LDFLAGS_u-boot += -pie +endif
# # FIXME: binutils versions < 2.22 have a bug in the assembler where @@ -95,6 +97,8 @@ endif endif
# check that only R_ARM_RELATIVE relocations are generated +ifndef CONFIG_ARM64 ifneq ($(CONFIG_SPL_BUILD),y) ALL-y += checkarmreloc endif +endif diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile new file mode 100644 index 0000000..b216f27 --- /dev/null +++ b/arch/arm/cpu/armv8/Makefile @@ -0,0 +1,38 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +#
+include $(TOPDIR)/config.mk
+LIB = $(obj)lib$(CPU).o
+START := start.o
+COBJS += cpu.o +COBJS += timer.o +COBJS += cache_v8.o
+SOBJS += exceptions.o +SOBJS += cache.o +SOBJS += tlb.o
+SRCS := $(START:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START))
+all: $(obj).depend $(START) $(LIB)
+$(LIB): $(OBJS)
- $(call cmd_link_o_target, $(OBJS))
+#########################################################################
+# defines $(obj).depend target +include $(SRCTREE)/rules.mk
+sinclude $(obj).depend
+######################################################################### diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S new file mode 100644 index 0000000..419f169 --- /dev/null +++ b/arch/arm/cpu/armv8/cache.S @@ -0,0 +1,130 @@ +/*
- (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/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 /* isb to sych the new cssr & csidr */
- mrs x6, ccsidr_el1 /* read the new ccsidr */
- and x2, x6, #7 /* x2 <- length of the cache lines */
- add x2, x2, #4 /* add 4 (line length offset) */
- mov x3, #0x3ff
- and x3, x3, x6, lsr #3 /* x3 <- maximum number of way size */
- clz w5, w3 /* bit position of way size */
- mov x4, #0x7fff
- and x4, x4, x1, lsr #13 /* x4 <- max number of the set size */
- /* x1 <- cache level << 1 */
- /* x2 <- line length offset */
- /* x3 <- number of cache ways */
- /* x4 <- number of cache sets */
- /* x5 <- bit position of way size */
+loop_set:
- mov x6, x3 /* create working copy of way size */
+loop_way:
- lsl x7, x6, x5
- orr x9, x0, 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
- mov x15, lr
- mrs x10, clidr_el1 /* read clidr */
- lsr x11, x10, #24
- and x11, x11, #0x7 /* x11 <- loc */
- cbz x11, finished /* if loc is 0, no need to clean */
- mov x0, #0 /* start flush at cache level 0 */
- /* x0 <- cache level */
- /* x10 <- clidr_el1 */
- /* x11 <- loc */
+loop_level:
- lsl x1, x0, #1
- add x1, x1, x0 /* x0 <- 3x 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
+finished:
- mov x0, #0
- msr csselr_el1, x0 /* swith back to cache level 0 */
- dsb sy
- isb
- mov lr, x15
- 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 /* read CTR */
- lsr x3, x3, #16
- and x3, x3, #0xf /* cache line size encoding */
- mov x2, #4 /* bytes per word */
- lsl x2, x2, x3 /* actual 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 D/unified line */
- 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) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c new file mode 100644 index 0000000..34426fd --- /dev/null +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -0,0 +1,218 @@ +/*
- (C) Copyright 2013
- David Feng fenghua@phytium.com.cn
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/system.h> +#include <asm/arch/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 < (PAGE_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 = curent_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
panic("Not Supported Exception Level");
- /* 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);
+} diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk new file mode 100644 index 0000000..9f36d59 --- /dev/null +++ b/arch/arm/cpu/armv8/config.mk @@ -0,0 +1,16 @@ +# +# (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) +PLATFORM_CPPFLAGS += -fpic diff --git a/arch/arm/cpu/armv8/cpu.c b/arch/arm/cpu/armv8/cpu.c new file mode 100644 index 0000000..83e73ab --- /dev/null +++ b/arch/arm/cpu/armv8/cpu.c @@ -0,0 +1,67 @@ +/*
- (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+
- */
+/*
- CPU specific code
- */
+#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <linux/compiler.h>
+void __weak cpu_cache_initialization(void){}
+int cleanup_before_linux(void) +{
- /*
* this function is called just before we call linux
* it prepares the processor for linux
*
* we turn off caches etc ...
*/
+#ifndef CONFIG_SPL_BUILD
- disable_interrupts();
+#endif
- /*
* 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();
- /*
* After D-cache is flushed and before it is disabled there may
* be some new valid entries brought into the cache. We are sure
* that these lines are not dirty and will not affect our execution.
* (because unwinding the call-stack and setting a bit in CP15 SCTRL
* is all we did during this. We have not pushed anything on to the
* stack. Neither have we affected any static data)
* So just invalidate the entire d-cache again to avoid coherency
* problems for kernel
*/
- invalidate_dcache_all();
- /*
* Some CPU need more cache attention before starting the kernel.
*/
- cpu_cache_initialization();
- return 0;
+} diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S new file mode 100644 index 0000000..b2f62c9 --- /dev/null +++ b/arch/arm/cpu/armv8/exceptions.S @@ -0,0 +1,115 @@ +/*
- (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 EL1 or EL2 */
- mrs x11, CurrentEL
- cmp x11, 0x4
- b.eq 1f
- cmp x11, 0x8
- b.eq 2f
- b 3f
+1: mrs x1, esr_el1
- mrs x2, elr_el1
- b 3f
+2: mrs x1, esr_el2
- mrs x2, elr_el2
+3:
- 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
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S new file mode 100644 index 0000000..28c8fe3 --- /dev/null +++ b/arch/arm/cpu/armv8/start.S @@ -0,0 +1,234 @@ +/*
- (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/arch/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
*/
- mrs x0, CurrentEL
- cmp x0, #0xc
- b.ne reset_nonsecure /* Not EL3 */
- bl setup_el3 /* EL3 initialization */
- /*
* MMU Disabled, iCache Disabled, dCache Disabled
*/
+reset_nonsecure:
+#ifdef CONFIG_BOOTING_EL1
- switch_el1_el2 x0, 1f, 2f, 3f
+1: b 3f +2: bl setup_el2 /* EL2 initialization */ +3: +#endif
- /* Initialize vBAR/CPACR_EL1/MDSCR_EL1 */
- adr x0, vectors
- switch_el1_el2 x1, 1f, 2f, 3f
+1: msr vbar_el1, x0
- mov x0, #3 << 20
- msr cpacr_el1, x0 /* Enable FP/SIMD */
- msr mdscr_el1, xzr
- b 3f
+2: msr vbar_el2, x0 +3:
- /* 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_slave x0, slave_cpu
- /*
* Master CPU
*/
+master_cpu:
- bl _main
- /*
* Slave CPUs
*/
+slave_cpu:
- wfe
- ldr x1, =SECONDARY_CPU_MAILBOX
This is platform specific. Not all platforms will boot secondary cores into u-boot.
You could simply ifdef this code with SECONDARY_CPU_MAILBOX.
- ldr x0, [x1]
- cbz x0, slave_cpu
- br x0 /* branch to the given address */
+/*-------------------------------------------------------------------------*/
+WEAK(setup_el3)
This function should be optional so platforms don't have to define GIC_DIST_BASE, GIC_CPU_BASE, and CONFIG_SYS_CNTFRQ.
- mov x0, #0x531 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */
- msr scr_el3, x0
- msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */
- /* GIC initialization */
- branch_if_slave x0, 2f
- /* Master initialize distributor */
- ldr x1, =GIC_DIST_BASE /* GICD_CTLR */
- mov w0, #0x3 /* Enable Group0 & Group1 */
- str w0, [x1]
- ldr w0, [x1, #0x4] /* GICD_TYPER */
- and w2, w0, #0x1f /* ITLinesNumber */
- add w2, w2, #0x1 /* Number of GICD_IGROUPR registers */
- add x1, x1, #0x80 /* GICD_IGROUPR */
- mov w0, #~0 /* All Group1 */
+1: str w0, [x1], #0x4
- sub w2, w2, #0x1
- cbnz w2, 1b
- b 3f
- /* Slave initialize distributor */
+2: ldr x1, =GIC_DIST_BASE /* GICD_CTLR */
- mov w0, #~0 /* All Group1 */
- str w0, [x1, #0x80]
- /* Initialize cpu interface */
+3: ldr x1, =GIC_CPU_BASE /* GICC_CTLR */
- mov w0, #0x3 /* Enable Group0 & Group1 */
- str w0, [x1]
- mov w0, #0x1 << 7 /* Non-Secure access to GICC_PMR */
- str w0, [x1, #0x4] /* GICC_PMR */
- /* Counter frequency initialization */
- ldr x0, =CONFIG_SYS_CNTFRQ
- msr cntfrq_el0, x0
- /* SCTLR_EL2 initialization */
- msr sctlr_el2, xzr
- /* Return to the EL2_SP2 mode from EL3 */
- mov x0, #0x3c9 /* EL2_SP2 | D | A | I | F */
- msr elr_el3, lr
- msr spsr_el3, x0
- eret
+ENDPROC(setup_el3)
+WEAK(setup_el2)
- /* Initialize Generic Timers */
- mrs x0, cnthctl_el2
- orr x0, x0, #0x3 /* Enable EL1 access to timers */
- msr cnthctl_el2, x0
- msr cntvoff_el2, x0 /* Clear virtual offset */
- mrs x0, cntkctl_el1
- orr x0, x0, #0x3 /* EL0 access to counters */
- 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 CP15 traps to EL2 */
- /* 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, #0x3c5 /* EL1_SP1 | D | A | I | F */
- msr elr_el2, lr
- msr spsr_el2, x0
- eret
+ENDPROC(setup_el2)
+WEAK(lowlevel_init)
- 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. Using 512GB address range.
*/
- ldr x0, =MEMORY_ATTRIBUTES
- ldr x1, =TCR_FLAGS
- switch_el1_el2 x2, 1f, 2f, 3f
+1: orr x1, x1, TCR_EL1_IPS_40BIT
- msr mair_el1, x0
- msr tcr_el1, x1
- b 3f
+2: orr x1, x1, TCR_EL2_IPS_40BIT
- msr mair_el2, x0
- msr tcr_el2, x1
+3: +#endif
- /* Relocate vBAR */
- adr x0, vectors
- switch_el1_el2 x1, 1f, 2f, 3f
+1: msr vbar_el1, x0
- b 3f
+2: msr vbar_el2, x0 +3:
- ret
+ENDPROC(c_runtime_cpu_setup) diff --git a/arch/arm/cpu/armv8/timer.c b/arch/arm/cpu/armv8/timer.c new file mode 100644 index 0000000..9605e84 --- /dev/null +++ b/arch/arm/cpu/armv8/timer.c @@ -0,0 +1,80 @@ +/*
- (C) Copyright 2013
- David Feng fenghua@phytium.com.cn
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <div64.h> +#include <linux/compiler.h>
+/*
- Genertic Timer implementation of __udelay/get_timer/get_ticks/get_tbclk
- functions. If any other timers used, another implementation should be
- placed in platform code.
- */
+static inline u64 get_cntfrq(void) +{
- u64 cntfrq;
- asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
- return cntfrq;
+}
+static inline u64 tick_to_time(u64 tick) +{
- tick *= CONFIG_SYS_HZ;
- do_div(tick, get_cntfrq());
- return tick;
+}
+static inline u64 time_to_tick(u64 time) +{
- time *= get_cntfrq();
- do_div(time, CONFIG_SYS_HZ);
- return time;
+}
+/*
- Generic timer implementation of get_tbclk()
- */
+ulong __weak get_tbclk(void) +{
- return CONFIG_SYS_HZ;
You should return get_cntfreq here.
+}
+/*
- Generic timer implementation of get_timer()
- */
+ulong __weak get_timer(ulong base) +{
- u64 cval;
- isb();
- asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
- return tick_to_time(cval) - base;
+}
+/*
- Generic timer implementation of get_ticks()
- */
+unsigned long long __weak get_ticks(void) +{
- return get_timer(0);
+}
+/*
- Generic timer implementation of __udelay()
- */
+void __weak __udelay(ulong usec) +{
- unsigned long ticks, limit;
- limit = get_ticks() + usec/1000;
Your udelay implementation has 1 msec resolution. It should use the raw timer to get usec resolution.
- do {
ticks = get_ticks();
- } while (ticks < limit);
+} diff --git a/arch/arm/cpu/armv8/tlb.S b/arch/arm/cpu/armv8/tlb.S new file mode 100644 index 0000000..6bb1e1f --- /dev/null +++ b/arch/arm/cpu/armv8/tlb.S @@ -0,0 +1,30 @@ +/*
- (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_el1_el2 x9, 1f, 2f, 3f
+1: tlbi vmalle1
- dsb sy
- isb
- b 3f
+2: tlbi alle2
- dsb sy
- isb
+3:
- ret
+ENDPROC(__asm_invalidate_tlb_all) diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds new file mode 100644 index 0000000..328d477 --- /dev/null +++ b/arch/arm/cpu/armv8/u-boot.lds @@ -0,0 +1,71 @@ +/*
- (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);
- .reloc : {
__rel_got_start = .;
*(.got)
__rel_got_end = .;
- }
- .image_copy_end :
- {
*(.__image_copy_end)
- }
- _end = .;
- . = ALIGN(8);
- .bss : {
__bss_start = .;
*(.bss*)
. = ALIGN(8);
__bss_end = .;
- }
- /DISCARD/ : { *(.dynsym) }
- /DISCARD/ : { *(.dynstr*) }
- /DISCARD/ : { *(.dynamic*) }
- /DISCARD/ : { *(.plt*) }
- /DISCARD/ : { *(.interp*) }
- /DISCARD/ : { *(.gnu*) }
+} diff --git a/arch/arm/include/asm/arch-armv8/gpio.h b/arch/arm/include/asm/arch-armv8/gpio.h new file mode 100644 index 0000000..afe7ece --- /dev/null +++ b/arch/arm/include/asm/arch-armv8/gpio.h @@ -0,0 +1,11 @@ +/*
- (C) Copyright 2013
- David Feng fenghua@phytium.com.cn
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _ASM_ARMV8_GPIO_H_ +#define _ASM_ARMV8_GPIO_H_
+#endif /* _ASM_ARMV8_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-armv8/mmu.h b/arch/arm/include/asm/arch-armv8/mmu.h new file mode 100644 index 0000000..33b3246 --- /dev/null +++ b/arch/arm/include/asm/arch-armv8/mmu.h @@ -0,0 +1,110 @@ +/*
- (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 (39)
+/* 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) | \
(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_40BIT (2 << 32) +#define TCR_EL2_IPS_40BIT (2 << 16)
+/* 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_ */ diff --git a/arch/arm/include/asm/byteorder.h b/arch/arm/include/asm/byteorder.h index c3489f1..71a9966 100644 --- a/arch/arm/include/asm/byteorder.h +++ b/arch/arm/include/asm/byteorder.h @@ -23,10 +23,22 @@ # define __SWAB_64_THRU_32__ #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__ #include <linux/byteorder/big_endian.h> #else #include <linux/byteorder/little_endian.h> #endif
+#endif /* CONFIG_ARM64 */
#endif diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index 6d60a4a..ddebbc8 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h @@ -11,6 +11,8 @@
#include <asm/system.h>
+#ifndef CONFIG_ARM64
/*
- 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 dram_bank_mmu_setup(int bank);
+#endif
/*
- 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
diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h index 99b703e..0ee131d 100644 --- a/arch/arm/include/asm/config.h +++ b/arch/arm/include/asm/config.h @@ -9,4 +9,14 @@
#define CONFIG_LMB #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#ifdef CONFIG_ARM64 +/*
- Currently, GOT is used to relocate u-boot and
- configuration CONFIG_NEEDS_MANUAL_RELOC is needed.
- */
+#define CONFIG_NEEDS_MANUAL_RELOC +#define CONFIG_PHYS_64BIT +#endif
#endif diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 79a9597..30a338e 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -47,6 +47,10 @@ struct arch_global_data {
#include <asm-generic/global_data.h>
-#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") +#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 ("r8") +#endif
#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1fbc531..6a1f05a 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.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_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; while(bytelen--) __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; while(wordlen--) __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; while(longlen--) __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; while(bytelen--) *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; while(wordlen--) *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; while(longlen--) diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index ff13f36..db8869e 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -54,5 +54,44 @@ bcs 1b .endm
+#ifdef CONFIG_ARM64 +/*
- Register aliases.
- */
+lr .req x30
+/*
- Branch according to exception level
- */
+.macro switch_el1_el2, xreg, el1_label, el2_label, fail_label
- mrs \xreg, CurrentEL
- cmp \xreg, 0x4
- b.eq \el1_label
- cmp \xreg, 0x8
- b.eq \el2_label
- b \fail_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
+#endif /* CONFIG_ARM64 */
#endif /* __ASSEMBLY__ */ #endif /* __ASM_ARM_MACRO_H__ */ diff --git a/arch/arm/include/asm/posix_types.h b/arch/arm/include/asm/posix_types.h index c412486..9ba9add 100644 --- a/arch/arm/include/asm/posix_types.h +++ b/arch/arm/include/asm/posix_types.h @@ -13,6 +13,8 @@ #ifndef __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
- 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_uid_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 int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; +#endif /* CONFIG_ARM64 */
typedef long __kernel_time_t; typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; diff --git a/arch/arm/include/asm/proc-armv/ptrace.h b/arch/arm/include/asm/proc-armv/ptrace.h index 79cc644..fd280cb 100644 --- a/arch/arm/include/asm/proc-armv/ptrace.h +++ b/arch/arm/include/asm/proc-armv/ptrace.h @@ -12,6 +12,25 @@
#include <linux/config.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 FIQ26_MODE 0x01 #define IRQ26_MODE 0x02 @@ -106,4 +125,6 @@ static inline int valid_user_regs(struct pt_regs *regs)
#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_ARM64 */
#endif diff --git a/arch/arm/include/asm/proc-armv/system.h b/arch/arm/include/asm/proc-armv/system.h index b4cfa68..19b2b44 100644 --- a/arch/arm/include/asm/proc-armv/system.h +++ b/arch/arm/include/asm/proc-armv/system.h @@ -15,6 +15,60 @@ /*
- 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) \ ({ \ unsigned long temp; \ @@ -109,7 +163,10 @@ : "r" (x) \ : "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
- cache totally. This means that the cache becomes inconsistent, and,
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 760345f..e79f790 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -1,6 +1,79 @@ #ifndef __ASM_ARM_SYSTEM_H #define __ASM_ARM_SYSTEM_H
+#ifdef CONFIG_ARM64
+/*
- SCTLR_EL2 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 curent_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 = curent_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
panic("Not Supported Exception Level");
- return val;
+}
+static inline void set_sctlr(unsigned int val) +{
- unsigned int el;
- el = curent_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
panic("Not Supported Exception Level");
- 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);
+#endif /* __ASSEMBLY__ */
+#else /* CONFIG_ARM64 */
#ifdef __KERNEL__
#define CPU_ARCH_UNKNOWN 0 @@ -45,6 +118,8 @@ #define CR_AFE (1 << 29) /* Access flag 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
- asked it for some inline assembly sequences. Apparently we can't trust
@@ -132,4 +207,6 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop);
#endif /* __KERNEL__ */
+#endif /* CONFIG_ARM64 */
#endif diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h index 71dc049..2326420 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/asm/types.h @@ -39,7 +39,11 @@ typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64;
+#ifdef CONFIG_ARM64 +#define BITS_PER_LONG 64 +#else /* CONFIG_ARM64 */ #define BITS_PER_LONG 32 +#endif /* CONFIG_ARM64 */
/* Dma addresses are 32-bits wide. */
diff --git a/arch/arm/include/asm/u-boot.h b/arch/arm/include/asm/u-boot.h index 2b5fce8..cb81232 100644 --- a/arch/arm/include/asm/u-boot.h +++ b/arch/arm/include/asm/u-boot.h @@ -44,6 +44,10 @@ typedef struct bd_info { #endif /* !CONFIG_SYS_GENERIC_BOARD */
/* For image.h:image_check_target_arch() */ +#ifndef CONFIG_ARM64 #define IH_ARCH_DEFAULT IH_ARCH_ARM +#else +#define IH_ARCH_DEFAULT IH_ARCH_ARM64 +#endif
#endif /* _U_BOOT_H_ */ diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h index 44593a8..0a228fb 100644 --- a/arch/arm/include/asm/unaligned.h +++ b/arch/arm/include/asm/unaligned.h @@ -8,7 +8,7 @@ /*
- Select endianness
*/ -#ifndef __ARMEB__ +#if __BYTE_ORDER == __LITTLE_ENDIAN #define get_unaligned __get_unaligned_le #define put_unaligned __put_unaligned_le #else diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 4e78723..03c31c7 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -10,6 +10,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).o LIBGCC = $(obj)libgcc.o
+ifdef CONFIG_ARM64 +SOBJS-y += crt0_64.o +else GLSOBJS += _ashldi3.o GLSOBJS += _ashrdi3.o GLSOBJS += _divsi3.o @@ -21,9 +24,14 @@ GLSOBJS += _umodsi3.o GLCOBJS += div0.o
SOBJS-y += crt0.o +endif
ifndef CONFIG_SPL_BUILD +ifdef CONFIG_ARM64 +SOBJS-y += relocate_64.o +else SOBJS-y += relocate.o +endif ifndef CONFIG_SYS_GENERIC_BOARD COBJS-y += board.o endif @@ -38,11 +46,17 @@ else COBJS-$(CONFIG_SPL_FRAMEWORK) += spl.o endif
+ifdef CONFIG_ARM64 +COBJS-y += interrupts_64.o +else COBJS-y += interrupts.o +endif COBJS-y += reset.o
COBJS-y += cache.o +ifndef CONFIG_ARM64 COBJS-y += cache-cp15.o +endif
SRCS := $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \ $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 34f50b0..d6d0833 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -344,7 +344,7 @@ void board_init_f(ulong bootflag)
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) /* reserve TLB table */
- gd->arch.tlb_size = 4096 * 4;
gd->arch.tlb_size = PGTABLE_SIZE; addr -= gd->arch.tlb_size;
/* round down to next 64 kB limit */
@@ -419,6 +419,7 @@ void board_init_f(ulong bootflag) } #endif
+#ifndef CONFIG_ARM64 /* setup stackpointer for exeptions */ gd->irq_sp = addr_sp; #ifdef CONFIG_USE_IRQ @@ -431,6 +432,10 @@ void board_init_f(ulong bootflag)
/* 8-byte alignment for ABI compliance */ addr_sp &= ~0x07; +#else /* CONFIG_ARM64 */
- /* 16-byte alignment for ABI compliance */
- addr_sp &= ~0x0f;
+#endif /* CONFIG_ARM64 */ #else addr_sp += 128; /* leave 32 words for abort-stack */ gd->irq_sp = addr_sp; @@ -513,7 +518,15 @@ void board_init_r(gd_t *id, ulong dest_addr) ulong flash_size; #endif
/*
* Relocate routines of serial_device first so that
* printf access the correct puts function. This is critical
* when CONFIG_NEEDS_MANUAL_RELOC is needed.
*/
serial_initialize();
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
monitor_flash_len = _end_ofs;
@@ -523,6 +536,15 @@ void board_init_r(gd_t *id, ulong dest_addr)
debug("monitor flash len: %08lX\n", monitor_flash_len); board_init(); /* Setup chipselects */
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
- /*
* We have to relocate the command table manually
*/
- fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
ll_entry_count(cmd_tbl_t, cmd));
+#endif /* CONFIG_NEEDS_MANUAL_RELOC */
- /*
- TODO: printing of the clock inforamtion of the board is now
- implemented as part of bdinfo command. Currently only support for
@@ -532,7 +554,6 @@ void board_init_r(gd_t *id, ulong dest_addr) #ifdef CONFIG_CLOCKS set_cpu_clk_info(); /* Setup clock information */ #endif
serial_initialize();
debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index eefb456..26e85f0 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -222,6 +222,21 @@ static void boot_prep_linux(bootm_headers_t *images) /* Subcommand: GO */ 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; char *s; void (*kernel_entry)(int zero, int arch, uint params); @@ -248,6 +263,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
if (!fake) kernel_entry(0, machid, r2); +#endif }
/* Main Entry point for arm bootm implementation diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S new file mode 100644 index 0000000..ddd46eb --- /dev/null +++ b/arch/arm/lib/crt0_64.S @@ -0,0 +1,116 @@ +/*
- 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:
- 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.
- 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)
- 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.
- Call relocate_code(). This function relocates U-Boot from its
- current location into the relocation destination computed by
- board_init_f().
- 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.
- 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 x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */
- ldr x0, =__bss_start
- add x0, x0, x9 /* x0 <- __bss_start in RAM */
- ldr x1, =__bss_end
- add x1, x1, x9 /* x1 <- __bss_end in RAM */
- 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) diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c new file mode 100644 index 0000000..b476722 --- /dev/null +++ b/arch/arm/lib/interrupts_64.c @@ -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");
+} diff --git a/arch/arm/lib/relocate_64.S b/arch/arm/lib/relocate_64.S new file mode 100644 index 0000000..29c3239 --- /dev/null +++ b/arch/arm/lib/relocate_64.S @@ -0,0 +1,57 @@ +/*
- 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.
- NOTE:
- GOT is used and configuration CONFIG_NEEDS_MANUAL_RELOC is needed.
- */
+ENTRY(relocate_code)
- /*
* Copy u-boot from flash to RAM
*/
- ldr x1, =__image_copy_start /* x1 <- copy source */
- cmp x1, x0
- b.eq relocate_done /* skip relocation */
- mov x2, x0 /* x2 <- copy destination */
- ldr x3, =__image_copy_end /* x3 <- source end address */
+copy_loop:
- ldp x10, x11, [x1], #16 /* copy from source address [x1] */
- stp x10, x11, [x2], #16 /* copy to target address [x2] */
- cmp x1, x3 /* until source end address [x3] */
- b.lo copy_loop
- /*
* Fix .reloc relocations
*/
- ldr x9, [x18, #GD_RELOC_OFF]/* x9 <- relocation offset */
- ldr x1, =__rel_got_start /* x1 <- rel got start ofs */
- add x1, x1, x9 /* x1 <- rel got start in RAM */
- ldr x2, =__rel_got_end /* x2 <- rel got end ofs */
- add x2, x2, x9 /* x2 <- rel got end in RAM */
+fixloop:
- ldr x10, [x1]
- add x10, x10, x9 /* x10 <- address to be fixed up */
- str x10, [x1]
- add x1, x1, #8 /* each got entry is 8 bytes */
- cmp x1, x2
- b.lo fixloop
+relocate_done:
- ret
+ENDPROC(relocate_code) diff --git a/common/image.c b/common/image.c index b0ae58f..4145354 100644 --- a/common/image.c +++ b/common/image.c @@ -81,6 +81,7 @@ static const table_entry_t uimage_arch[] = { { IH_ARCH_NDS32, "nds32", "NDS32", }, { IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",}, { IH_ARCH_SANDBOX, "sandbox", "Sandbox", },
- { IH_ARCH_ARM64, "arm64", "AArch64", }, { -1, "", "", },
};
diff --git a/doc/README.arm64 b/doc/README.arm64 new file mode 100644 index 0000000..746ce6a --- /dev/null +++ b/doc/README.arm64 @@ -0,0 +1,33 @@ +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 could be running at EL1 or EL2.
s/Currenly/Currently/
+2. Currenly, U-boot for arm64 is compiled with AArch64-gcc. AArch64-gcc
s/Currenly/Currently/
- use rela relocation format, it cannot be relocated during running. So,
- GOT is used to relocate u-boot and CONFIG_NEEDS_MANUAL_RELOC is needed.
+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. Generic board is supported.
+5. 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
- Simon Glass sjg@chromium.org
- Sharma Bhupesh bhupesh.sharma@freescale.com
- Rob Herring robherring2@gmail.com
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c index 8fb1765..fc5d7ef 100644 --- a/examples/standalone/stubs.c +++ b/examples/standalone/stubs.c @@ -39,6 +39,20 @@ gd_t *global_data; " bctr\n" \ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11"); #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 /*
- r8 holds the pointer to the global_data, ip is a call-clobbered
- register
@@ -50,6 +64,7 @@ gd_t *global_data; " ldr ip, [r8, %0]\n" \ " ldr pc, [ip, %1]\n" \ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip"); +#endif #elif defined(CONFIG_MIPS) /*
- k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
diff --git a/include/image.h b/include/image.h index ee6eb8d..7de2bb2 100644 --- a/include/image.h +++ b/include/image.h @@ -156,6 +156,7 @@ struct lmb; #define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */ #define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */ #define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */ +#define IH_ARCH_ARM64 22 /* ARM64 */
/*
- Image Types

On 10/03/2013 04:35 PM, Rob Herring wrote:
On 09/26/2013 08:35 AM, fenghua@phytium.com.cn wrote:
From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn
arch/arm/config.mk | 4 +
FYI, some recent mainline changes to config.mk break the build for me.
arch/arm/cpu/armv8/Makefile | 38 +++++ arch/arm/cpu/armv8/cache.S | 130 +++++++++++++++++ arch/arm/cpu/armv8/cache_v8.c | 218 ++++++++++++++++++++++++++++ arch/arm/cpu/armv8/config.mk | 16 +++ arch/arm/cpu/armv8/cpu.c | 67 +++++++++ arch/arm/cpu/armv8/exceptions.S | 115 +++++++++++++++ arch/arm/cpu/armv8/start.S | 234 +++++++++++++++++++++++++++++++ arch/arm/cpu/armv8/timer.c | 80 +++++++++++ arch/arm/cpu/armv8/tlb.S | 30 ++++ arch/arm/cpu/armv8/u-boot.lds | 71 ++++++++++ arch/arm/include/asm/arch-armv8/gpio.h | 11 ++ arch/arm/include/asm/arch-armv8/mmu.h | 110 +++++++++++++++
Also, this directory is mutually exclusive with arch-${soc}. I think this should be moved up a level. gpio.h is probably fine as a default version.
Rob

On 10/03/2013 02:51 PM, Rob Herring wrote:
On 10/03/2013 04:35 PM, Rob Herring wrote:
On 09/26/2013 08:35 AM, fenghua@phytium.com.cn wrote:
From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn
arch/arm/config.mk | 4 +
FYI, some recent mainline changes to config.mk break the build for me.
arch/arm/cpu/armv8/Makefile | 38 +++++ arch/arm/cpu/armv8/cache.S | 130 +++++++++++++++++ arch/arm/cpu/armv8/cache_v8.c | 218 ++++++++++++++++++++++++++++ arch/arm/cpu/armv8/config.mk | 16 +++ arch/arm/cpu/armv8/cpu.c | 67 +++++++++ arch/arm/cpu/armv8/exceptions.S | 115 +++++++++++++++ arch/arm/cpu/armv8/start.S | 234 +++++++++++++++++++++++++++++++ arch/arm/cpu/armv8/timer.c | 80 +++++++++++ arch/arm/cpu/armv8/tlb.S | 30 ++++ arch/arm/cpu/armv8/u-boot.lds | 71 ++++++++++ arch/arm/include/asm/arch-armv8/gpio.h | 11 ++ arch/arm/include/asm/arch-armv8/mmu.h | 110 +++++++++++++++
Also, this directory is mutually exclusive with arch-${soc}. I think this should be moved up a level. gpio.h is probably fine as a default version.
I am also concerned about gpio.h. I am forced to create a gpio.h file even I don't use it when I add soc for armv8.
York

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/03/2013 05:54 PM, York Sun wrote:
On 10/03/2013 02:51 PM, Rob Herring wrote:
On 10/03/2013 04:35 PM, Rob Herring wrote:
On 09/26/2013 08:35 AM, fenghua@phytium.com.cn wrote:
From: David Feng fenghua@phytium.com.cn
Signed-off-by: David Feng fenghua@phytium.com.cn
arch/arm/config.mk | 4 +
FYI, some recent mainline changes to config.mk break the build for me.
arch/arm/cpu/armv8/Makefile | 38 +++++ arch/arm/cpu/armv8/cache.S | 130 +++++++++++++++++ arch/arm/cpu/armv8/cache_v8.c | 218 ++++++++++++++++++++++++++++ arch/arm/cpu/armv8/config.mk | 16 +++ arch/arm/cpu/armv8/cpu.c | 67 +++++++++ arch/arm/cpu/armv8/exceptions.S | 115 +++++++++++++++ arch/arm/cpu/armv8/start.S | 234 +++++++++++++++++++++++++++++++ arch/arm/cpu/armv8/timer.c | 80 +++++++++++ arch/arm/cpu/armv8/tlb.S | 30 ++++ arch/arm/cpu/armv8/u-boot.lds | 71 ++++++++++ arch/arm/include/asm/arch-armv8/gpio.h | 11 ++ arch/arm/include/asm/arch-armv8/mmu.h | 110 +++++++++++++++
Also, this directory is mutually exclusive with arch-${soc}. I think this should be moved up a level. gpio.h is probably fine as a default version.
I am also concerned about gpio.h. I am forced to create a gpio.h file even I don't use it when I add soc for armv8.
Yes, gpio.h belongs elsewhere, and we should not be making symlinks for arch-armv8, we should just have asm/armv8/ and asm/armv7/ and reference them directly,
- -- Tom
participants (4)
-
fenghua@phytium.com.cn
-
Rob Herring
-
Tom Rini
-
York Sun