Allwinner A64 SoC (and probably others) boots in 32-bits mode. Switching to aarch64 is achieved by writing to the Reset Management Register (RMR) which can be accessed through the memory space thanks to an alias. On A64 this alias is located at 0x017000a0 --- arch/arm/include/asm/barebox.lds.h | 2 ++ arch/arm/mach-sunxi/Kconfig | 5 ++++ arch/arm/mach-sunxi/Makefile | 2 ++ arch/arm/mach-sunxi/rmr_switch.S | 47 ++++++++++++++++++++++++++++++ include/mach/sunxi/barebox.lds.h | 6 ++++ include/mach/sunxi/rmr_switch.h | 10 +++++++ 6 files changed, 72 insertions(+) create mode 100644 arch/arm/mach-sunxi/rmr_switch.S create mode 100644 include/mach/sunxi/barebox.lds.h create mode 100644 include/mach/sunxi/rmr_switch.h diff --git a/arch/arm/include/asm/barebox.lds.h b/arch/arm/include/asm/barebox.lds.h index a5c74381d8..f94290128e 100644 --- a/arch/arm/include/asm/barebox.lds.h +++ b/arch/arm/include/asm/barebox.lds.h @@ -2,6 +2,8 @@ #if defined CONFIG_ARCH_EP93XX #include <mach/ep93xx/barebox.lds.h> +#elif defined CONFIG_ARCH_SUNXI +#include <mach/sunxi/barebox.lds.h> #endif #ifdef CONFIG_CPU_32 diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 0e8d83fedd..e28f04c354 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -4,6 +4,11 @@ config ARCH_TEXT_BASE hex default 0x0 +config SUNXI_RVBAR_IOMAP + hex + default 0x017000a0 if ARCH_SUN50I_A64 + # default 0x09010040 if ARCH_SUN50I_H5 + menuconfig SUNXI_MULTI_BOARDS bool "Allwinner boards" select HAVE_PBL_MULTI_IMAGES diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index d678973ca2..e7fa23c832 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -1,2 +1,4 @@ obj-y += sunxi.o lwl-y += cpu_init.o + +pbl-$(CONFIG_CPU_64) += rmr_switch.o diff --git a/arch/arm/mach-sunxi/rmr_switch.S b/arch/arm/mach-sunxi/rmr_switch.S new file mode 100644 index 0000000000..bfe3b75e3a --- /dev/null +++ b/arch/arm/mach-sunxi/rmr_switch.S @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * ARMv8 RMR reset sequence on Allwinner SoCs. + * + * All 64-bit capable Allwinner SoCs reset in AArch32 (and continue to + * exectute the Boot ROM in this state), so we need to switch to AArch64 + * at some point. + * Section G6.2.133 of the ARMv8 ARM describes the Reset Management Register + * (RMR), which triggers a warm-reset of a core and can request to switch + * into a different execution state (AArch32 or AArch64). + * The address at which execution starts after the reset is held in the + * RVBAR system register, which is architecturally read-only. + * Allwinner provides a writable alias of this register in MMIO space, so + * we can easily set the start address of AArch64 code. + * This code below switches to AArch64 and starts execution at the specified + * start address. + * + * This file has been adapted from U-Boot code sources: + * - arch/arm/mach-sunxi/rmr_switch.S + * - arch/arm/include/asm/arch-sunxi/boot0.h. + * + * The aarch32 assembly has already been assembled and are inserted verbatime + * as .word statements (the asm source is commented for each statement). + * + */ + +#include <config.h> +#include <linux/linkage.h> + +.section .text_head_rmr_switch, "x" +ENTRY(sunxi_rmr_switch) /* arm32 arm64 */ + .word 0xeb000000 /* bl .+8 subs x0, x0, x0 */ + b end /* .word 0x1400000c b end */ + .word 0xe59f0020 /* ldr r0, [pc, #32] ; rvbar */ + .word 0xe580e000 /* str lr, [r0] */ + .word 0xf57ff04f /* dsb sy */ + .word 0xf57ff06f /* isb syo */ + .word 0xee1c0f50 /* mrc 15, 0, r0, cr12, cr0, {2} */ + .word 0xe3800003 /* orr r0, r0, #3 */ + .word 0xee0c0f50 /* mcr 15, 0, r0, cr12, cr0, {2} */ + .word 0xf57ff06f /* isb sy */ + .word 0xe320f003 /* 1b: wfi */ + .word 0xeafffffd /* b 1b */ + .word CONFIG_SUNXI_RVBAR_IOMAP + .align 3 /* prevent linker script from adding padding for aligment */ +end: /* fall-through */ +ENDPROC(sunxi_rmr_switch) diff --git a/include/mach/sunxi/barebox.lds.h b/include/mach/sunxi/barebox.lds.h new file mode 100644 index 0000000000..e04c713611 --- /dev/null +++ b/include/mach/sunxi/barebox.lds.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* theses two sections should only be needed for the pbl */ +#define ENTRY_HEADER \ + *(.text_head_egon_header*) \ + *(.text_head_rmr_switch*) diff --git a/include/mach/sunxi/rmr_switch.h b/include/mach/sunxi/rmr_switch.h new file mode 100644 index 0000000000..2ecbd81d57 --- /dev/null +++ b/include/mach/sunxi/rmr_switch.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef __MACH_RMR_SWITCH_H +#define __MACH_RMR_SWITCH_H + +/* 64-bits Allwinner SoCs reset in AArch32 and need to switch to AArch64 */ +extern const u32 sunxi_rmr_switch[]; +#define sunxi_switch_to_aarch64() __keep_symbolref(sunxi_rmr_switch) + +#endif -- 2.40.0