rockchip: back-to-bootrom: replace assembly-implementation with C-code
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>
Tue, 10 Oct 2017 14:21:14 +0000 (16:21 +0200)
committerPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>
Tue, 21 Nov 2017 22:57:22 +0000 (23:57 +0100)
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>
arch/arm/include/asm/arch-rockchip/bootrom.h
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/bootrom.c
arch/arm/mach-rockchip/save_boot_param.S [deleted file]

index 169cc5e50b0e982be3132cb523ec8ceb4c62e948..2f61a338116bded179bd78975edac573349d4c5e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * (C) Copyright 2017 Heiko Stuebner <heiko@sntech.de>
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:    GPL-2.0
  */
 extern u32 SAVE_SP_ADDR;
 
 /**
- * Hand control back to the bootrom to load another
- * boot stage.
+ * back_to_bootrom() - return to bootrom (for TPL/SPL), passing a
+ *                     result code
+ *
+ * Transfer control back to the Rockchip BROM, restoring necessary
+ * register context and passing a command/result code to the BROM
+ * to instruct its next actions (e.g. continue boot sequence, enter
+ * download mode, ...).
+ *
+ * This function does not return.
  */
-void back_to_bootrom(void);
+enum rockchip_bootrom_cmd {
+       /*
+        * These can not start at 0, as 0 has a special meaning
+        * for setjmp().
+        */
 
-/**
- * Assembler component for the above (do not call this directly)
- */
-void _back_to_bootrom_s(void);
+       BROM_BOOT_NEXTSTAGE = 1,  /* continue boot-sequence */
+       BROM_BOOT_ENTER_DNL,      /* have BROM enter download-mode */
+};
+
+void back_to_bootrom(void);
 
 /**
  * Boot-device identifiers as used by the BROM
index daafc8de6a8a059298bc942d34e102d144ca4ec8..b875dfc6b0dfccbc288ec217f1fd987e94f57bdc 100644 (file)
@@ -8,8 +8,8 @@
 # this may have entered from ATF with the stack-pointer pointing to
 # inaccessible/protected memory (and the bootrom-helper assumes that
 # the stack-pointer is valid before switching to the U-Boot stack).
-obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
-obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o
+obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
+obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o
 
 obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o
 obj-tpl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-tpl.o
index 8380e4e00613b8c2cd8e4fc587226b51d6dba2e1..7b9b307a89c403d662264d99ff1fdce1b6ee0c90 100644 (file)
@@ -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;
 }
diff --git a/arch/arm/mach-rockchip/save_boot_param.S b/arch/arm/mach-rockchip/save_boot_param.S
deleted file mode 100644 (file)
index 50fce20..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * (C) Copyright 2016 Rockchip Electronics Co., Ltd
- * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
- *
- * SPDX-License-Identifier:     GPL-2.0+
- */
-
-#include <linux/linkage.h>
-
-#if defined(CONFIG_ARM64)
-.globl SAVE_SP_ADDR
-SAVE_SP_ADDR:
-       .quad 0
-
-ENTRY(save_boot_params)
-       sub     sp, sp, #0x60
-       stp     x29, x30, [sp, #0x50]
-       stp     x27, x28, [sp, #0x40]
-       stp     x25, x26, [sp, #0x30]
-       stp     x23, x24, [sp, #0x20]
-       stp     x21, x22, [sp, #0x10]
-       stp     x19, x20, [sp, #0]
-       ldr     x8, =SAVE_SP_ADDR
-       mov     x9, sp
-       str     x9, [x8]
-       b       save_boot_params_ret  /* back to my caller */
-ENDPROC(save_boot_params)
-
-.globl _back_to_bootrom_s
-ENTRY(_back_to_bootrom_s)
-       ldr     x0, =SAVE_SP_ADDR
-       ldr     x0, [x0]
-       mov     sp, x0
-       ldp     x29, x30, [sp, #0x50]
-       ldp     x27, x28, [sp, #0x40]
-       ldp     x25, x26, [sp, #0x30]
-       ldp     x23, x24, [sp, #0x20]
-       ldp     x21, x22, [sp, #0x10]
-       ldp     x19, x20, [sp]
-       add     sp, sp, #0x60
-       mov     x0, xzr
-       ret
-ENDPROC(_back_to_bootrom_s)
-#else
-.globl SAVE_SP_ADDR
-SAVE_SP_ADDR:
-       .word 0
-
-/*
- * void save_boot_params
- *
- * Save sp, lr, r1~r12
- */
-ENTRY(save_boot_params)
-       push    {r1-r12, lr}
-       ldr     r0, =SAVE_SP_ADDR
-       str     sp, [r0]
-       b       save_boot_params_ret            @ back to my caller
-ENDPROC(save_boot_params)
-
-
-.globl _back_to_bootrom_s
-ENTRY(_back_to_bootrom_s)
-       ldr     r0, =SAVE_SP_ADDR
-       ldr     sp, [r0]
-       mov     r0, #0
-       pop     {r1-r12, pc}
-ENDPROC(_back_to_bootrom_s)
-#endif