summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/lib/crt0.S3
-rw-r--r--common/init/board_init.c8
-rw-r--r--common/spl/spl.c26
3 files changed, 22 insertions, 15 deletions
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index 4f2a7121c4..2f4c14e96b 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -85,6 +85,8 @@ ENTRY(_main)
mov r0, sp
bl board_init_f_alloc_reserve
mov sp, r0
+ /* set up gd here, outside any C code */
+ mov r9, r0
bl board_init_f_init_reserve
mov r0, #0
@@ -134,6 +136,7 @@ here:
bl spl_relocate_stack_gd
cmp r0, #0
movne sp, r0
+ movne r9, r0
# endif
ldr r0, =__bss_start /* this is auto-relocated! */
diff --git a/common/init/board_init.c b/common/init/board_init.c
index e649e078b9..d98648eaa6 100644
--- a/common/init/board_init.c
+++ b/common/init/board_init.c
@@ -21,13 +21,13 @@ DECLARE_GLOBAL_DATA_PTR;
#define _USE_MEMCPY
#endif
-/* Unfortunately x86 can't compile this code as gd cannot be assigned */
-#ifndef CONFIG_X86
+/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */
+#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
__weak void arch_setup_gd(struct global_data *gd_ptr)
{
gd = gd_ptr;
}
-#endif /* !CONFIG_X86 */
+#endif /* !CONFIG_X86 && !CONFIG_ARM */
/*
* Allocate reserved space for use as 'globals' from 'top' address and
@@ -128,7 +128,7 @@ void board_init_f_init_reserve(ulong base)
*ptr++ = 0;
#endif
/* set GD unless architecture did it already */
-#ifndef CONFIG_X86
+#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
arch_setup_gd(gd_ptr);
#endif
/* next alloc will be higher by one GD plus 16-byte alignment */
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 6e6dee7ec9..e5167bf73e 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -431,8 +431,13 @@ void preloader_console_init(void)
* 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.
+ * place, sets the new gd (except for ARM, for which setting GD within a C
+ * function may not always work) and returns the new stack position. The
+ * caller is responsible for setting up the sp register and, in the case
+ * of ARM, setting up gd.
+ *
+ * All of this is done using the same layout and alignments as done in
+ * board_init_f_init_reserve() / board_init_f_alloc_reserve().
*
* @return new stack location, or 0 to use the same stack
*/
@@ -440,14 +445,7 @@ 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_ADDR - sizeof(gd_t);
- ptr &= ~7;
- new_gd = (gd_t *)ptr;
- memcpy(new_gd, (void *)gd, sizeof(gd_t));
- gd = new_gd;
+ ulong ptr = CONFIG_SPL_STACK_R_ADDR;
#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
@@ -460,7 +458,13 @@ ulong spl_relocate_stack_gd(void)
gd->malloc_ptr = 0;
}
#endif
-
+ /* Get stack position: use 8-byte alignment for ABI compliance */
+ ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16);
+ new_gd = (gd_t *)ptr;
+ memcpy(new_gd, (void *)gd, sizeof(gd_t));
+#if !defined(CONFIG_ARM)
+ gd = new_gd;
+#endif
return ptr;
#else
return 0;
OpenPOWER on IntegriCloud