diff options
author | Philipp Tomsich <philipp.tomsich@theobroma-systems.com> | 2017-09-15 12:33:10 +0200 |
---|---|---|
committer | Philipp Tomsich <philipp.tomsich@theobroma-systems.com> | 2017-10-02 11:20:55 +0200 |
commit | aaaaaa2d4863e69063dee36d7bbe70108f84806c (patch) | |
tree | daa53ea72ba8a0c6bbee85c7c90d1c36a56e8625 /arch/arm/mach-rockchip/bootrom.c | |
parent | cbddcc7fc309c251e2cf6677324ff0c772007159 (diff) |
rockchip: back-to-bootrom: replace assembly-implementation with C-code
The back-to-bootrom implementation for Rockchip has always relied on
the stack-pointer being valid on entry, so there was little reason to
have this as an assembly implementation.
This provides a new C-only implementation of save_boot_params and
back_to_bootrom (relying on setjmp/longjmp) and removes the older
assembly-only implementation.
Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Tested-by: Andy Yan <andy.yan@rock-chips.com>
Series-cc: Andy Yan <andy.yan@rock-chips.com>
Series-cc: Klaus Goger <klaus.goger@theobroma-systems.com>
Series-version: 3
Cover-letter:
rockchip: back-to-bootrom: replace assembly-implementation with C-code
Recent discussions confirmed (what the code always assumed): the
Rockchip BROM always enters U-Boot with the stack-pointer valid
(i.e. the U-Boot startup code is running off the BROM stack).
We can thus replace the back-to-bootrom code (i.e. both the
save_boot_params and back_to_bootrom implementations) using C-code
based on setjmp/longjmp. The new implementation is already structured
to allow an easy drop-in of Andy's changes to enter download-mode when
returning to the BROM.
This turned out to require a some tweaking to system.h (making sure
that the prototype for save_boot_params_ret is visible for A64)and
start.S (so binutils knows that this is a possible function entry and
it can correctly insert A32-to-Thumb transitions) and taking the axe
to setjmp.h (which created quite a few issues with it not expecting
A32/T32/Thumb call-sites and some fragility from GCC being smart about
the clobber-list of the inline assembly... which led to r9 not being
saved or restored).
END
Diffstat (limited to 'arch/arm/mach-rockchip/bootrom.c')
-rw-r--r-- | arch/arm/mach-rockchip/bootrom.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index 8380e4e006..7b9b307a89 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -6,11 +6,61 @@ #include <common.h> #include <asm/arch/bootrom.h> +#include <asm/setjmp.h> +#include <asm/system.h> + +/* + * Force the jmp_buf to the data-section, as .bss will not be valid + * when save_boot_params is invoked. + */ +static jmp_buf brom_ctx __section(".data"); void back_to_bootrom(void) { #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) puts("Returning to boot ROM...\n"); #endif - _back_to_bootrom_s(); + longjmp(brom_ctx, BROM_BOOT_NEXTSTAGE); +} + +/* + * All Rockchip BROM implementations enter with a valid stack-pointer, + * so this can safely be implemented in C (providing a single + * implementation both for ARMv7 and AArch64). + */ +int save_boot_params(void) +{ + int ret = setjmp(brom_ctx); + + switch (ret) { + case 0: + /* + * This is the initial pass through this function + * (i.e. saving the context), setjmp just setup up the + * brom_ctx: transfer back into the startup-code at + * 'save_boot_params_ret' and let the compiler know + * that this will not return. + */ + save_boot_params_ret(); + while (true) + /* does not return */; + break; + + case BROM_BOOT_NEXTSTAGE: + /* + * To instruct the BROM to boot the next stage, we + * need to return 0 to it: i.e. we need to rewrite + * the return code once more. + */ + ret = 0; + break; + + default: +#if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) + puts("FATAL: unexpected command to back_to_bootrom()\n"); +#endif + hang(); + }; + + return ret; } |