omap-common/spl: Add linux boot to SPL
authorSimon Schwarz <simonschwarzcor@googlemail.com>
Thu, 15 Mar 2012 04:01:38 +0000 (04:01 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Tue, 27 Mar 2012 20:05:28 +0000 (22:05 +0200)
This adds Linux booting to the SPL

This depends on CONFIG_MACH_TYPE patch by Igor Grinberg
(http://article.gmane.org/gmane.comp.boot-loaders.u-boot/105809)

Related CONFIGs:
CONFIG_SPL_OS_BOOT
Activates/Deactivates the OS booting feature
CONFIG_SPL_OS_BOOT_KEY
defines the IO-pin number u-boot switch - if pressed u-boot is
booted
CONFIG_SYS_NAND_SPL_KERNEL_OFFS
Offset in NAND of direct boot kernel image to use in SPL
CONFIG_SYS_SPL_ARGS_ADDR
Address where the kernel boot arguments are expected - this is
normaly RAM-begin + 0x100

Signed-off-by: Simon Schwarz <simonschwarzcor@gmail.com>
CC: Tom Rini <tom.rini@gmail.com>
CC: Stefano Babic <sbabic@denx.de>
CC: Wolfgang Denk <wd@denx.de>
arch/arm/cpu/armv7/omap-common/spl.c
arch/arm/cpu/armv7/omap-common/spl_nand.c
arch/arm/include/asm/omap_common.h

index 99bb382750ea402d7ef4595b596621dee110dbdd..6b54ac7f018efe6c419f4acd54db2d14fd06ed80 100644 (file)
@@ -65,6 +65,25 @@ void board_init_f(ulong dummy)
        relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE);
 }
 
+/*
+ * Default function to determine if u-boot or the OS should
+ * be started. This implementation always returns 1.
+ *
+ * Please implement your own board specific funcion to do this.
+ *
+ * RETURN
+ * 0 to not start u-boot
+ * positive if u-boot should start
+ */
+#ifdef CONFIG_SPL_OS_BOOT
+__weak int spl_start_uboot(void)
+{
+       printf("SPL: Please implement spl_start_uboot() for your board\n");
+       printf("SPL: Direct Linux boot not active!\n");
+       return 1;
+}
+#endif
+
 void spl_parse_image_header(const struct image_header *header)
 {
        u32 header_size = sizeof(struct image_header);
@@ -92,6 +111,24 @@ void spl_parse_image_header(const struct image_header *header)
        }
 }
 
+/*
+ * This function jumps to an image with argument. Normally an FDT or ATAGS
+ * image.
+ * arg: Pointer to paramter image in RAM
+ */
+#ifdef CONFIG_SPL_OS_BOOT
+static void __noreturn jump_to_image_linux(void *arg)
+{
+       debug("Entering kernel arg pointer: 0x%p\n", arg);
+       typedef void (*image_entry_arg_t)(int, int, void *)
+               __attribute__ ((noreturn));
+       image_entry_arg_t image_entry =
+               (image_entry_arg_t) spl_image.entry_point;
+       /* cleanup_before_linux(); */ /*write SPL function for that*/
+       image_entry(0, CONFIG_MACH_TYPE, arg);
+}
+#endif
+
 static void __noreturn jump_to_image_no_args(void)
 {
        typedef void __noreturn (*image_entry_noargs_t)(u32 *);
@@ -149,6 +186,13 @@ void board_init_r(gd_t *id, ulong dummy)
                debug("Jumping to U-Boot\n");
                jump_to_image_no_args();
                break;
+#ifdef CONFIG_SPL_OS_BOOT
+       case IH_OS_LINUX:
+               debug("Jumping to Linux\n");
+               spl_board_prepare_for_linux();
+               jump_to_image_linux((void *)CONFIG_SYS_SPL_ARGS_ADDR);
+               break;
+#endif
        default:
                puts("Unsupported OS image.. Jumping nevertheless..\n");
                jump_to_image_no_args();
index 2a6621492e984f2a36dd85b51abe2dc49cecc766..1295e88752473dab7217e14cf9c8ac38b1cc394b 100644 (file)
@@ -29,7 +29,6 @@
 #include <version.h>
 #include <asm/omap_common.h>
 
-
 void spl_nand_load_image(void)
 {
        struct image_header *header;
@@ -50,7 +49,7 @@ void spl_nand_load_image(void)
        /*use CONFIG_SYS_TEXT_BASE as temporary storage area */
        header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
 #ifdef CONFIG_SPL_OS_BOOT
-       if (!spl_uboot_key()) {
+       if (!spl_start_uboot()) {
                /*
                 * load parameter image
                 * load to temp position since nand_spl_load_image reads
@@ -74,31 +73,39 @@ void spl_nand_load_image(void)
                nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
                        CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
                spl_parse_image_header(header);
-               nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
-                       spl_image.size, (void *)spl_image.load_addr);
-       } else
+               if (header->ih_os == IH_OS_LINUX) {
+                       /* happy - was a linux */
+                       nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
+                               spl_image.size, (void *)spl_image.load_addr);
+                       nand_deselect();
+                       return;
+               } else {
+                       printf("The Expected Linux image was not"
+                               "found. Please check your NAND"
+                               "configuration.\n");
+                       printf("Trying to start u-boot now...\n");
+               }
+       }
 #endif
-       {
 #ifdef CONFIG_NAND_ENV_DST
-               nand_spl_load_image(CONFIG_ENV_OFFSET,
-                       CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
-               spl_parse_image_header(header);
-               nand_spl_load_image(CONFIG_ENV_OFFSET, spl_image.size,
-                       (void *)spl_image.load_addr);
+       nand_spl_load_image(CONFIG_ENV_OFFSET,
+               CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+       spl_parse_image_header(header);
+       nand_spl_load_image(CONFIG_ENV_OFFSET, spl_image.size,
+               (void *)spl_image.load_addr);
 #ifdef CONFIG_ENV_OFFSET_REDUND
-               nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND,
-                       CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
-               spl_parse_image_header(header);
-               nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, spl_image.size,
-                       (void *)spl_image.load_addr);
+       nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND,
+               CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+       spl_parse_image_header(header);
+       nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, spl_image.size,
+               (void *)spl_image.load_addr);
 #endif
 #endif
-               /* Load u-boot */
-               nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
-                       CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
-               spl_parse_image_header(header);
-               nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
-                       spl_image.size, (void *)spl_image.load_addr);
-       }
+       /* Load u-boot */
+       nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+               CONFIG_SYS_NAND_PAGE_SIZE, (void *)header);
+       spl_parse_image_header(header);
+       nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+               spl_image.size, (void *)spl_image.load_addr);
        nand_deselect();
 }
index 85eac7db599cecb762b41fba1be51f95b3746ef3..6f25948e20ea04a1e1b727efcd4a1ae9d691704a 100644 (file)
@@ -93,6 +93,7 @@ u32 omap_boot_mode(void);
 void spl_parse_image_header(const struct image_header *header);
 void omap_rev_string(void);
 void spl_board_prepare_for_linux(void);
+int spl_start_uboot(void);
 
 /* NAND SPL functions */
 void spl_nand_load_image(void);