aboutsummaryrefslogtreecommitdiff
path: root/common/spl/spl.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-03-03 08:03:00 -0700
committerTom Rini <trini@konsulko.com>2015-03-04 14:55:04 -0500
commitdb910353a126d84fe8dff7a694ea792f50fcfb6a (patch)
tree0cca558754e992284820fbc240690c13d0a00cb0 /common/spl/spl.c
parentbdfb34167f73afc7e04d52499fc14bc1cd33fec0 (diff)
downloadu-boot-db910353a126d84fe8dff7a694ea792f50fcfb6a.zip
u-boot-db910353a126d84fe8dff7a694ea792f50fcfb6a.tar.gz
u-boot-db910353a126d84fe8dff7a694ea792f50fcfb6a.tar.bz2
arm: spl: Allow board_init_r() to run with a larger stack
At present SPL uses a single stack, either CONFIG_SPL_STACK or CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and environment) require a lot of stack, some boards set CONFIG_SPL_STACK to point into SDRAM. They then set up SDRAM very early, before board_init_f(), so that the larger stack can be used. This is an abuse of lowlevel_init(). That function should only be used for essential start-up code which cannot be delayed. An example of a valid use is when only part of the SPL code is visible/executable, and the SoC must be set up so that board_init_f() can be reached. It should not be used for SDRAM init, console init, etc. Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new address before board_init_r() is called in SPL. The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README. Signed-off-by: Simon Glass <sjg@chromium.org> For version 1: Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net> Reviewed-by: Stefan Roese <sr@denx.de> Tested-by: Bo Shen <voice.shen@atmel.com> Acked-by: Bo Shen <voice.shen@atmel.com> Acked-by: Heiko Schocher <hs@denx.de> Tested-by: Heiko Schocher <hs@denx.de> Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'common/spl/spl.c')
-rw-r--r--common/spl/spl.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/common/spl/spl.c b/common/spl/spl.c
index ded0f30..cd75bbc 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -281,3 +281,38 @@ void preloader_console_init(void)
spl_display_print();
#endif
}
+
+/**
+ * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
+ *
+ * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
+ * for the main board_init_r() execution. This is typically because we need
+ * more stack space for things like the MMC sub-system.
+ *
+ * This function calculates the stack position, copies the global_data into
+ * place and returns the new stack position. The caller is responsible for
+ * setting up the sp register.
+ *
+ * @return new stack location, or 0 to use the same stack
+ */
+ulong spl_relocate_stack_gd(void)
+{
+#ifdef CONFIG_SPL_STACK_R
+ gd_t *new_gd;
+ ulong ptr;
+
+ /* Get stack position: use 8-byte alignment for ABI compliance */
+ ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
+ ptr &= ~7;
+ new_gd = (gd_t *)ptr;
+ memcpy(new_gd, (void *)gd, sizeof(gd_t));
+ gd = new_gd;
+
+ /* Clear the BSS. */
+ memset(__bss_start, 0, __bss_end - __bss_start);
+
+ return ptr;
+#else
+ return 0;
+#endif
+}