On 19/11/2020 19:59, Priit Laes wrote: > On Thu, Nov 19, 2020 at 10:54:42AM +0000, Andre Przywara wrote: >> So far we did not support the BootROM based FEL USB debug mode on the >> 64-bit builds for Allwinner SoCs: The BootROM is using AArch32, but the >> SPL runs in AArch64. >> Returning back to AArch32 was not working as expected, since the RMR >> reset into 32-bit mode always starts execution in the BootROM, but not >> in the FEL routine. >> >> After some debug and research and with help via IRC, the CPU hotplug >> mechanism emerged as a solution: If a certain R_CPUCFG register contains >> some magic, the BootROM will immediately branch to an address stored in >> some other register. This works well for our purposes. >> >> Enable the FEL feature by providing early AArch32 code to first save the >> FEL state, *before* initially entering AArch64. >> If we eventually determine that we should return to FEL, we reset back >> into AArch32, and use the CPU hotplug mechanism to run some small >> AArch32 code snippet that restores the initially saved FEL state. >> >> That allows the normal AArch64 SPL build to be loaded via the sunxi-fel >> tool, with it returning into FEL mode, so that other payloads can be >> transferred via FEL as well. >> >> Tested on A64, H5 and H6. >> >> Signed-off-by: Andre Przywara <andre.przyw...@arm.com> >> --- >> arch/arm/cpu/armv8/Makefile | 2 + >> arch/arm/cpu/armv8/fel_utils.S | 78 +++++++++++++++++++++++++ >> arch/arm/include/asm/arch-sunxi/boot0.h | 14 +++++ >> include/configs/sunxi-common.h | 2 - >> 4 files changed, 94 insertions(+), 2 deletions(-) >> create mode 100644 arch/arm/cpu/armv8/fel_utils.S > > Don't you want to also update board/sunxi/README.sunxi64 ?
Yes, but I am in the process of rewriting this anyway, since some parts apply to 32-bit SoCs as well (SD card, SPI flash), and there is currently no documentation about them. So bear with me, I will post a documentation update ASAP, just didn't want to hold back this patch. Thanks! Andre. >> >> diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile >> index 93d26f98568..f7b4a5ee46c 100644 >> --- a/arch/arm/cpu/armv8/Makefile >> +++ b/arch/arm/cpu/armv8/Makefile >> @@ -27,6 +27,8 @@ obj-$(CONFIG_ARM_SMCCC) += smccc-call.o >> >> ifndef CONFIG_SPL_BUILD >> obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o >> +else >> +obj-$(CONFIG_ARCH_SUNXI) += fel_utils.o >> endif >> obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o >> sec_firmware_asm.o >> >> diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S >> new file mode 100644 >> index 00000000000..334fdef7fa0 >> --- /dev/null >> +++ b/arch/arm/cpu/armv8/fel_utils.S >> @@ -0,0 +1,78 @@ >> +/* >> + * Utility functions for FEL mode, when running SPL in AArch64. >> + * >> + * Copyright (c) 2017 Arm Ltd. >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#include <asm-offsets.h> >> +#include <config.h> >> +#include <asm/system.h> >> +#include <linux/linkage.h> >> + >> +/* >> + * We don't overwrite save_boot_params() here, to save the FEL state upon >> + * entry, since this would run *after* the RMR reset, which clobbers that >> + * state. >> + * Instead we store the state _very_ early in the boot0 hook, *before* >> + * resetting to AArch64. >> + */ >> + >> +/* >> + * The FEL routines in BROM run in AArch32. >> + * Reset back into 32-bit mode here and restore the saved FEL state >> + * afterwards. >> + * Resetting back into AArch32/EL3 using the RMR always enters the BROM, >> + * but we can use the CPU hotplug mechanism to branch back to our code >> + * immediately. >> + */ >> +ENTRY(return_to_fel) >> + /* >> + * the RMR reset will clear all registers, so save the arguments >> + * (LR and SP) in the fel_stash structure, which we read anyways later >> + */ >> + adr x2, fel_stash >> + str w0, [x2] >> + str w1, [x2, #4] >> + >> + adr x1, fel_stash_addr // to find the fel_stash address in AA32 >> + str w2, [x1] >> + >> + ldr x0, =0xfa50392f // CPU hotplug magic >> +#ifndef CONFIG_MACH_SUN50I_H6 >> + ldr x2, =(SUNXI_CPUCFG_BASE + 0x1a4) // offset for CPU hotplug base >> + str w0, [x2, #0x8] >> +#else >> + ldr x2, =(SUNXI_RTC_BASE + 0x1b8) // BOOT_CPU_HP_FLAG_REG >> + str w0, [x2], #0x4 >> +#endif >> + adr x0, back_in_32 >> + str w0, [x2] >> + >> + dsb sy >> + isb sy >> + mov x0, #2 // RMR reset into AArch32 >> + dsb sy >> + msr RMR_EL3, x0 >> + isb sy >> +1: wfi >> + b 1b >> + >> +/* AArch32 code to restore the state from fel_stash and return back to FEL. >> */ >> +back_in_32: >> + .word 0xe59f0028 // ldr r0, [pc, #40] ; load fel_stash address >> + .word 0xe5901008 // ldr r1, [r0, #8] >> + .word 0xe129f001 // msr CPSR_fc, r1 >> + .word 0xf57ff06f // isb >> + .word 0xe590d000 // ldr sp, [r0] >> + .word 0xe590e004 // ldr lr, [r0, #4] >> + .word 0xe5901010 // ldr r1, [r0, #16] >> + .word 0xee0c1f10 // mcr 15, 0, r1, cr12, cr0, {0} ; VBAR >> + .word 0xe590100c // ldr r1, [r0, #12] >> + .word 0xee011f10 // mcr 15, 0, r1, cr1, cr0, {0} ; SCTLR >> + .word 0xf57ff06f // isb >> + .word 0xe12fff1e // bx lr ; return to FEL >> +fel_stash_addr: >> + .word 0x00000000 // receives fel_stash addr, by AA64 code above >> +ENDPROC(return_to_fel) >> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h >> b/arch/arm/include/asm/arch-sunxi/boot0.h >> index 54c144afd8c..46d0f0666c2 100644 >> --- a/arch/arm/include/asm/arch-sunxi/boot0.h >> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h >> @@ -15,6 +15,19 @@ >> tst x0, x0 // this is "b #0x84" in ARM >> b reset >> .space 0x7c >> + >> + .word 0xe28f0058 // add r0, pc, #88 >> + .word 0xe59f1054 // ldr r1, [pc, #84] >> + .word 0xe0800001 // add r0, r0, r1 >> + .word 0xe580d000 // str sp, [r0] >> + .word 0xe580e004 // str lr, [r0, #4] >> + .word 0xe10fe000 // mrs lr, CPSR >> + .word 0xe580e008 // str lr, [r0, #8] >> + .word 0xee11ef10 // mrc 15, 0, lr, cr1, cr0, {0} >> + .word 0xe580e00c // str lr, [r0, #12] >> + .word 0xee1cef10 // mrc 15, 0, lr, cr12, cr0, {0} >> + .word 0xe580e010 // str lr, [r0, #16] >> + >> .word 0xe59f1024 // ldr r1, [pc, #36] ; 0x170000a0 >> .word 0xe59f0024 // ldr r0, [pc, #36] ; CONFIG_*_TEXT_BASE >> .word 0xe5810000 // str r0, [r1] >> @@ -36,6 +49,7 @@ >> #else >> .word CONFIG_SYS_TEXT_BASE >> #endif >> + .word fel_stash - . >> #else >> /* normal execution */ >> b reset >> diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h >> index a6a4879523a..203cb10fbab 100644 >> --- a/include/configs/sunxi-common.h >> +++ b/include/configs/sunxi-common.h >> @@ -163,9 +163,7 @@ >> >> #define CONFIG_SYS_MONITOR_LEN (768 << 10) /* 768 KiB */ >> >> -#ifndef CONFIG_ARM64 /* AArch64 FEL support is not ready yet >> */ >> #define CONFIG_SPL_BOARD_LOAD_IMAGE >> -#endif >> >> /* >> * We cannot use expressions here, because expressions won't be evaluated in >> -- >> 2.17.5 >> >> -- >> You received this message because you are subscribed to the Google Groups >> "linux-sunxi" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to linux-sunxi+unsubscr...@googlegroups.com. >> To view this discussion on the web, visit >> https://groups.google.com/d/msgid/linux-sunxi/20201119105442.24711-1-andre.przywara%40arm.com. -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/0fd3cbb4-a2c9-85d5-5fbd-057bb654863d%40arm.com.