Andre, > On 21.02.2019, at 14:06, Alexander Graf <ag...@suse.de> wrote: > > On 02/21/2019 01:07 PM, Andre Przywara wrote: >> On Thu, 21 Feb 2019 12:52:50 +0100 >> Alexander Graf <ag...@suse.de> wrote: >> >>> On 02/21/2019 02:30 AM, Andre Przywara wrote: >>>> The ARMv8 capable Allwinner A64 SoC comes out of reset in AArch32 mode. >>>> To run AArch64 code, we have to trigger a warm reset via the RMR register, >>>> which proceeds with code execution at the address stored in the RVBAR >>>> register. >>>> If the bootable payload in the FIT image is using a different >>>> architecture than the SPL has been compiled for, enter it via this said >>>> RMR switch mechanism, by writing the entry point address into the MMIO >>>> mapped, writable version of the RVBAR register. >>>> Then the warm reset is triggered via a system register write. >>>> If the payload architecture is the same as the SPL, we use the normal >>>> branch as usual. >>>> >>>> Signed-off-by: Andre Przywara <andre.przyw...@arm.com> >>>> --- >>>> arch/arm/lib/spl.c | 14 +++++++++ >>>> arch/arm/mach-sunxi/Makefile | 3 ++ >>>> arch/arm/mach-sunxi/spl_switch.c | 64 >>>> ++++++++++++++++++++++++++++++++++++++++ >>>> 3 files changed, 81 insertions(+) >>>> create mode 100644 arch/arm/mach-sunxi/spl_switch.c >>>> >>>> diff --git a/arch/arm/lib/spl.c b/arch/arm/lib/spl.c >>>> index 33cc76ba3d..4d9370d232 100644 >>>> --- a/arch/arm/lib/spl.c >>>> +++ b/arch/arm/lib/spl.c >>>> @@ -73,3 +73,17 @@ void __noreturn jump_to_image_linux(struct >>>> spl_image_info *spl_image) >>>> } >>>> #endif /* CONFIG_ARM64 */ >>>> #endif >>>> + >>>> +u8 spl_genimg_get_arch_id(const char *arch_str) >>>> +{ >>>> + if (!arch_str) >>>> + return IH_ARCH_DEFAULT; >>>> + >>>> + if (!strcmp(arch_str, "arm")) >>>> + return IH_ARCH_ARM; >>>> + >>>> + if (!strcmp(arch_str, "arm64")) >>>> + return IH_ARCH_ARM64; >>>> + >>>> + return IH_ARCH_DEFAULT; >>>> +} >>>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile >>>> index 43a93e3085..5a5e10a024 100644 >>>> --- a/arch/arm/mach-sunxi/Makefile >>>> +++ b/arch/arm/mach-sunxi/Makefile >>>> @@ -39,4 +39,7 @@ obj-$(CONFIG_SPL_SPI_SUNXI) += spl_spi_sunxi.o >>>> obj-$(CONFIG_SUNXI_DRAM_DW) += dram_sunxi_dw.o >>>> obj-$(CONFIG_SUNXI_DRAM_DW) += dram_timings/ >>>> obj-$(CONFIG_DRAM_SUN50I_H6) += dram_sun50i_h6.o >>>> +obj-$(CONFIG_MACH_SUN50I) += spl_switch.o >>>> +obj-$(CONFIG_MACH_SUN50I_H5) += spl_switch.o >>>> +obj-$(CONFIG_MACH_SUN50I_H6) += spl_switch.o >>>> endif >>>> diff --git a/arch/arm/mach-sunxi/spl_switch.c >>>> b/arch/arm/mach-sunxi/spl_switch.c >>>> new file mode 100644 >>>> index 0000000000..1de43c2396 >>>> --- /dev/null >>>> +++ b/arch/arm/mach-sunxi/spl_switch.c >>>> @@ -0,0 +1,64 @@ >>>> +/* >>>> + * (C) Copyright 2016 ARM Ltd. >>>> + * >>>> + * SPDX-License-Identifier: GPL-2.0+ >>>> + */ >>>> + >>>> +#include <common.h> >>>> +#include <spl.h> >>>> + >>>> +#include <asm/io.h> >>>> +#include <asm/barriers.h> >>>> + >>>> +static void __noreturn jump_to_image_native(struct spl_image_info >>>> *spl_image) >>>> +{ >>>> + typedef void __noreturn (*image_entry_noargs_t)(void); >>>> + >>>> + image_entry_noargs_t image_entry = >>>> + (image_entry_noargs_t)spl_image->entry_point; >>>> + >>>> + image_entry(); >>>> +} >>>> + >>>> +static void __noreturn reset_rmr_switch(void) >>>> +{ >>>> +#ifdef CONFIG_ARM64 >>>> + __asm__ volatile ( "mrs x0, RMR_EL3\n\t" >>>> + "bic x0, x0, #1\n\t" /* Clear enter-in-64 bit */ >>>> + "orr x0, x0, #2\n\t" /* set reset request bit */ >>>> + "msr RMR_EL3, x0\n\t" >>>> + "isb sy\n\t" >>>> + "nop\n\t" >>>> + "wfi\n\t" >>>> + "b .\n" >>>> + ::: "x0"); >>>> +#else >>>> + __asm__ volatile ( "mrc 15, 0, r0, cr12, cr0, 2\n\t" >>>> + "orr r0, r0, #3\n\t" /* request reset in 64 bit */ >>>> + "mcr 15, 0, r0, cr12, cr0, 2\n\t" >>>> + "isb\n\t" >>>> + "nop\n\t" >>>> + "wfi\n\t" >>>> + "b .\n" >>>> + ::: "r0"); >>>> +#endif >>>> + while (1); /* to avoid a compiler warning about __noreturn */ >>>> +} >>>> + >>>> +void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) >>>> +{ >>>> + if (spl_image->arch == IH_ARCH_DEFAULT) { >>>> + debug("entering by branch\n"); >>>> + jump_to_image_native(spl_image); >>>> + } else { >>>> + debug("entering by RMR switch\n"); >>>> +#ifdef CONFIG_MACH_SUN50I_H6 >>>> + writel(spl_image->entry_point, 0x09010040); >>>> +#else >>>> + writel(spl_image->entry_point, 0x017000a0); >>>> +#endif >>> How does the original entry point get preserved over this? Don't you >>> have to set the reset vector register as well? >> The RVBAR_ELx (Reset Vector Base Address Register) registers are >> architecturally read only. Fortunately Allwinner decided to have an MMIO >> mapped writable alias, which we exploit here. I *believe* this gets reset >> on a hard reset (external signal, for instance via the watchdog) to the >> initial 0x0 value. >> >> Anyway we use this method already in the AArch64 SPL today [1], and it >> happens to work ;-) > > Ugh, I read writel() the wrong way around. Do you think you can give the > constant a nice #define that makes it fully obvious what's going on here?
I have been preaching this for rockchip-changes: please use a “u32 * const” instead of a define... The compiler has a typesystem, so let’s provide the necessary info to fully use it ;-) Cheers, Philipp. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot