arm: spear: Support returning to BootROM
[oweals/u-boot.git] / arch / arm / cpu / arm926ejs / spear / spl.c
index b004cccafd593449a3ff5dc2c555597316a01bae..b2cacf2d3ef52b97e4538b935898ffeebc7d7174 100644 (file)
 #include <asm/arch/spr_syscntl.h>
 #include <linux/mtd/st_smi.h>
 
+/* Reserve some space to store the BootROM's stack pointer during SPL operation.
+ * The BSS cannot be used for this purpose because it will be zeroed after
+ * having stored the pointer, so force the location to the data section.
+ */
+u32 bootrom_stash_sp __attribute__((section(".data")));
+
 static void ddr_clock_init(void)
 {
        struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
@@ -223,8 +229,9 @@ u32 spl_boot_device(void)
 {
        u32 mode = 0;
 
-       /* Currently only SNOR is supported as the only */
-       if (snor_boot_selected()) {
+       if (usb_boot_selected()) {
+               mode = BOOT_DEVICE_BOOTROM;
+       } else if (snor_boot_selected()) {
                /* SNOR-SMI initialization */
                snor_init();
 
@@ -252,3 +259,27 @@ void board_init_f(ulong dummy)
        mpmc_init();
        spear_late_init();
 }
+
+/*
+ * In a few cases (Ethernet, UART or USB boot, we might want to go back into the
+ * BootROM code right after having initialized a few components like the DRAM).
+ * The following function is called from SPL common code (board_init_r).
+ */
+void board_return_to_bootrom(void)
+{
+       /*
+        * Retrieve the BootROM's stack pointer and jump back to the start of
+        * the SPL, where we can easily branch back into the BootROM. Don't do
+        * it right here because SPL might be compiled in Thumb mode while the
+        * BootROM expects ARM mode.
+        */
+       asm volatile ("ldr r0, =bootrom_stash_sp;"
+                     "ldr r0, [r0];"
+                     "mov sp, r0;"
+#if defined(CONFIG_SPL_SYS_THUMB_BUILD)
+                     "blx back_to_bootrom;"
+#else
+                     "bl back_to_bootrom;"
+#endif
+                     );
+}