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
bl spl_relocate_stack_gd
cmp r0, #0
movne sp, r0
+ movne r9, r0
# endif
ldr r0, =__bss_start /* this is auto-relocated! */
#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
*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 */
* 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
*/
{
#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) {
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;