summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-01-17 12:01:52 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2014-01-29 11:25:05 +0100
commitf77e5b938564b3d1193b55bbab42d79449699397 (patch)
tree41c284d938b8c799604ab5dd8d7d480cb723e5ed /arch
parent9399c7444d8f04e449a0c7d54c99aa437a13ca22 (diff)
downloadbarebox-f77e5b938564b3d1193b55bbab42d79449699397.tar.gz
barebox-f77e5b938564b3d1193b55bbab42d79449699397.tar.xz
ARM: i.MX: external NAND boot: make it work with relocatable PBL
We used to copy the initial binary portion from NFC SRAM to TEXT_BASE and jumped there. With relocatable PBL TEXT_BASE becomes 0, so this doesn't work. This is changed to copy the initial binary portion to the beginning of SDRAM instead. Tested on Phytec phyCARD-i.MX27 and Karo TX25 with and without relocatable pbl. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/external-nand-boot.c107
1 files changed, 50 insertions, 57 deletions
diff --git a/arch/arm/mach-imx/external-nand-boot.c b/arch/arm/mach-imx/external-nand-boot.c
index 4d86ab9d48..8c88e4bb23 100644
--- a/arch/arm/mach-imx/external-nand-boot.c
+++ b/arch/arm/mach-imx/external-nand-boot.c
@@ -28,6 +28,10 @@
#include <mach/imx31-regs.h>
#include <mach/imx35-regs.h>
+#define BARE_INIT_FUNCTION(name) \
+ __section(.text_bare_init_##name) \
+ name
+
static void __bare_init noinline imx_nandboot_wait_op_done(void *regs)
{
u32 r;
@@ -235,50 +239,6 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
}
}
-/*
- * This function assumes the currently running binary has been
- * copied from its current position to an offset. It returns
- * to the calling function - offset.
- * NOTE: The calling function may not return itself since it still
- * works on the old content of the lr register. Only call this
- * from a __noreturn function.
- */
-static __bare_init __naked void jump_sdram(unsigned long offset)
-{
- flush_icache();
-
- __asm__ __volatile__ (
- "sub lr, lr, %0;"
- "mov pc, lr;" : : "r"(offset)
- );
-}
-
-/*
- * Load and start barebox from NAND. This function also checks if we are really
- * running inside the NFC address space. If not, barebox is started from the
- * currently running address without loading anything from NAND.
- */
-int __bare_init imx_barebox_boot_nand_external(unsigned long nfc_base)
-{
- u32 r;
- u32 *src, *trg;
- int i;
-
- /* skip NAND boot if not running from NFC space */
- r = get_pc();
- if (r < nfc_base || r > nfc_base + 0x800)
- return 0;
-
- src = (unsigned int *)nfc_base;
- trg = (unsigned int *)ld_var(_text);
-
- /* Move ourselves out of NFC SRAM */
- for (i = 0; i < 0x800 / sizeof(int); i++)
- *trg++ = *src++;
-
- return 1;
-}
-
static inline int imx21_pagesize_2k(void)
{
if (readl(MX21_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
@@ -319,10 +279,6 @@ static inline int imx35_pagesize_2k(void)
return 0;
}
-#define BARE_INIT_FUNCTION(name) \
- void __noreturn __section(.text_bare_init_##name) \
- name
-
/*
* SoC specific entries for booting in external NAND mode. To be called from
* the board specific entry code. This is safe to call even if not booting from
@@ -332,20 +288,57 @@ static inline int imx35_pagesize_2k(void)
#define DEFINE_EXTERNAL_NAND_ENTRY(soc) \
\
-BARE_INIT_FUNCTION(imx##soc##_barebox_boot_nand_external)(void) \
+void __noreturn BARE_INIT_FUNCTION(imx##soc##_boot_nand_external_cont)(void) \
{ \
unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \
+ unsigned long sdram = MX##soc##_CSD0_BASE_ADDR; \
+ \
+ imx_nand_load_image((void *)sdram, \
+ ld_var(_barebox_image_size), \
+ (void *)nfc_base, \
+ imx##soc##_pagesize_2k()); \
+ \
+ imx##soc##_barebox_entry(0); \
+} \
+ \
+void __noreturn BARE_INIT_FUNCTION(imx##soc##_barebox_boot_nand_external)(void) \
+{ \
+ unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \
+ unsigned long sdram = MX##soc##_CSD0_BASE_ADDR; \
+ unsigned long __fn; \
+ u32 r; \
+ u32 *src, *trg; \
+ int i; \
+ void __noreturn (*fn)(void); \
+ \
+ /* skip NAND boot if not running from NFC space */ \
+ r = get_pc(); \
+ if (r < nfc_base || r > nfc_base + 0x800) \
+ imx##soc##_barebox_entry(0); \
+ \
+ src = (unsigned int *)nfc_base; \
+ trg = (unsigned int *)sdram; \
+ \
+ /* \
+ * Copy initial binary portion from NFC SRAM to beginning of \
+ * SDRAM \
+ */ \
+ for (i = 0; i < 0x800 / sizeof(int); i++) \
+ *trg++ = *src++; \
\
- if (imx_barebox_boot_nand_external(nfc_base)) { \
- jump_sdram(nfc_base - ld_var(_text)); \
+ /* The next function we jump to */ \
+ __fn = (unsigned long)imx##soc##_boot_nand_external_cont; \
+ /* mask out TEXT_BASE */ \
+ __fn &= 0x7ff; \
+ /* \
+ * and add sdram base instead where we copied the initial \
+ * binary above \
+ */ \
+ __fn += sdram; \
\
- imx_nand_load_image((void *)ld_var(_text), \
- ld_var(_barebox_image_size), \
- (void *)nfc_base, \
- imx##soc##_pagesize_2k()); \
- } \
+ fn = (void *)__fn; \
\
- imx##soc##_barebox_entry(0); \
+ fn(); \
}
#ifdef BROKEN