diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-01-17 12:01:52 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-01-29 11:25:05 +0100 |
commit | f77e5b938564b3d1193b55bbab42d79449699397 (patch) | |
tree | 41c284d938b8c799604ab5dd8d7d480cb723e5ed /arch | |
parent | 9399c7444d8f04e449a0c7d54c99aa437a13ca22 (diff) | |
download | barebox-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.c | 107 |
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 |