Allow arch-specific setting of global_data in board_init_f_mem()
authorSimon Glass <sjg@chromium.org>
Tue, 11 Aug 2015 02:44:30 +0000 (20:44 -0600)
committerSimon Glass <sjg@chromium.org>
Fri, 14 Aug 2015 15:50:10 +0000 (09:50 -0600)
At present we have a simple assignment to gd. With some archs this is
implemented as a register or through some other means; a simple assignment
does not suit in all cases.

Change this to a function and add documentation to describe how this all
works.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: York Sun <yorksun@freescale.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
common/board_f.c
include/common.h

index 74f77f1ea1c494094f079ad38293e2433d28010f..37b7bf5e360fe40a90a48e894d6b0c272f62f31f 100644 (file)
@@ -1027,16 +1027,25 @@ void board_init_f_r(void)
 }
 #endif /* CONFIG_X86 */
 
+/* Unfortunately x86 can't compile this code as gd cannot be assigned */
 #ifndef CONFIG_X86
+__weak void arch_setup_gd(struct global_data *gd_ptr)
+{
+       gd = gd_ptr;
+}
+
 ulong board_init_f_mem(ulong top)
 {
+       struct global_data *gd_ptr;
+
        /* Leave space for the stack we are running with now */
        top -= 0x40;
 
        top -= sizeof(struct global_data);
        top = ALIGN(top, 16);
-       gd = (struct global_data *)top;
-       memset((void *)gd, '\0', sizeof(*gd));
+       gd_ptr = (struct global_data *)top;
+       memset(gd_ptr, '\0', sizeof(*gd));
+       arch_setup_gd(gd_ptr);
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
        top -= CONFIG_SYS_MALLOC_F_LEN;
index 5c076d6ce184dd7d7cc1d4dfd447a613db3c47aa..c48e5bc11bf5b7ffe1d6f4314a17aa431b247b9a 100644 (file)
@@ -217,6 +217,49 @@ extern char console_buffer[];
 /* arch/$(ARCH)/lib/board.c */
 void board_init_f(ulong);
 void board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
+
+/**
+ * board_init_f_mem() - Allocate global data and set stack position
+ *
+ * This function is called by each architecture very early in the start-up
+ * code to set up the environment for board_init_f(). It allocates space for
+ * global_data (see include/asm-generic/global_data.h) and places the stack
+ * below this.
+ *
+ * This function requires a stack[1] Normally this is at @top. The function
+ * starts allocating space from 64 bytes below @top. First it creates space
+ * for global_data. Then it calls arch_setup_gd() which sets gd to point to
+ * the global_data space and can reserve additional bytes of space if
+ * required). Finally it allocates early malloc() memory
+ * (CONFIG_SYS_MALLOC_F_LEN). The new top of the stack is just below this,
+ * and it returned by this function.
+ *
+ * [1] Strictly speaking it would be possible to implement this function
+ * in C on many archs such that it does not require a stack. However this
+ * does not seem hugely important as only 64 byte are wasted. The 64 bytes
+ * are used to handle the calling standard which generally requires pushing
+ * addresses or registers onto the stack. We should be able to get away with
+ * less if this becomes important.
+ *
+ * @top:       Top of available memory, also normally the top of the stack
+ * @return:    New stack location
+ */
+ulong board_init_f_mem(ulong top);
+
+/**
+ * arch_setup_gd() - Set up the global_data pointer
+ *
+ * This pointer is special in some architectures and cannot easily be assigned
+ * to. For example on x86 it is implemented by adding a specific record to its
+ * Global Descriptor Table! So we we provide a function to carry out this task.
+ * For most architectures this can simply be:
+ *
+ *    gd = gd_ptr;
+ *
+ * @gd_ptr:    Pointer to global data
+ */
+void arch_setup_gd(gd_t *gd_ptr);
+
 int checkboard(void);
 int show_board_info(void);
 int checkflash(void);