diff --git a/arch/arm/boards/eukrea_cpuimx25/lowlevel.c b/arch/arm/boards/eukrea_cpuimx25/lowlevel.c index c16316d..95159bb 100644 --- a/arch/arm/boards/eukrea_cpuimx25/lowlevel.c +++ b/arch/arm/boards/eukrea_cpuimx25/lowlevel.c @@ -130,7 +130,7 @@ writel(0x82216080, MX25_ESDCTL_BASE_ADDR + IMX_ESDCTL0); if (IS_ENABLED(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND)) - imx25_barebox_boot_nand_external(0); + imx25_barebox_boot_nand_external(); out: imx25_barebox_entry(NULL); diff --git a/arch/arm/boards/eukrea_cpuimx35/lowlevel.c b/arch/arm/boards/eukrea_cpuimx35/lowlevel.c index ab5235f..4bb41b0 100644 --- a/arch/arm/boards/eukrea_cpuimx35/lowlevel.c +++ b/arch/arm/boards/eukrea_cpuimx35/lowlevel.c @@ -135,7 +135,7 @@ r |= 0x1 << 28; writel(r, MX35_CCM_BASE_ADDR + MX35_CCM_PDR4); - imx35_barebox_boot_nand_external(0); + imx35_barebox_boot_nand_external(); } out: diff --git a/arch/arm/boards/guf-cupid/lowlevel.c b/arch/arm/boards/guf-cupid/lowlevel.c index 0d7cfb6..60dd567 100644 --- a/arch/arm/boards/guf-cupid/lowlevel.c +++ b/arch/arm/boards/guf-cupid/lowlevel.c @@ -308,7 +308,7 @@ r0 |= 0x1 << 28; writel(r0, MX35_CCM_BASE_ADDR + MX35_CCM_PDR4); - imx35_barebox_boot_nand_external(0); + imx35_barebox_boot_nand_external(); } out: diff --git a/arch/arm/boards/guf-neso/lowlevel.c b/arch/arm/boards/guf-neso/lowlevel.c index 20f48be..3ae70ec 100644 --- a/arch/arm/boards/guf-neso/lowlevel.c +++ b/arch/arm/boards/guf-neso/lowlevel.c @@ -89,7 +89,7 @@ MX27_ESDCTL_BASE_ADDR + IMX_ESDCTL0); if (IS_ENABLED(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND)) - imx27_barebox_boot_nand_external(0); + imx27_barebox_boot_nand_external(); out: imx27_barebox_entry(NULL); diff --git a/arch/arm/boards/karo-tx25/lowlevel.c b/arch/arm/boards/karo-tx25/lowlevel.c index f79cd91..6c34944 100644 --- a/arch/arm/boards/karo-tx25/lowlevel.c +++ b/arch/arm/boards/karo-tx25/lowlevel.c @@ -74,7 +74,24 @@ writel(esdctl, esdctlreg); } -static void __bare_init karo_tx25_common_init(void *fdt) +extern char __dtb_imx25_karo_tx25_start[]; + +static void __noreturn karo_tx25_start(void) +{ + void *fdt; + + fdt = __dtb_imx25_karo_tx25_start + get_runtime_offset(); + + imx25_barebox_entry(fdt); +} + +static void __noreturn karo_tx25_load_nand(void) +{ + imx25_nand_load_image(); + karo_tx25_start(); +} + +static void __bare_init karo_tx25_common_init(void) { uint32_t r; @@ -138,7 +155,7 @@ /* Skip SDRAM initialization if we run from RAM */ r = get_pc(); if (r > 0x80000000 && r < 0xa0000000) - goto out; + karo_tx25_start(); /* set to 3.3v SDRAM */ writel(0x800, MX25_IOMUXC_BASE_ADDR + 0x454); @@ -156,21 +173,12 @@ setup_sdram(0x80000000, ESDCTLVAL, ESDCFGVAL); setup_sdram(0x90000000, ESDCTLVAL, ESDCFGVAL); - imx25_barebox_boot_nand_external(fdt); - -out: - imx25_barebox_entry(fdt); + imx25_nand_relocate_to_sdram(karo_tx25_load_nand); } -extern char __dtb_imx25_karo_tx25_start[]; - ENTRY_FUNCTION(start_imx25_karo_tx25, r0, r1, r2) { - void *fdt; - arm_setup_stack(MX25_IRAM_BASE_ADDR + MX25_IRAM_SIZE); - fdt = __dtb_imx25_karo_tx25_start + get_runtime_offset(); - - karo_tx25_common_init(fdt); + karo_tx25_common_init(); } diff --git a/arch/arm/boards/phytec-phycard-imx27/lowlevel.c b/arch/arm/boards/phytec-phycard-imx27/lowlevel.c index bd46df0..40d3968 100644 --- a/arch/arm/boards/phytec-phycard-imx27/lowlevel.c +++ b/arch/arm/boards/phytec-phycard-imx27/lowlevel.c @@ -77,7 +77,24 @@ MX27_ESDCTL_BASE_ADDR + IMX_ESDCTL0); } -static void __bare_init __naked phytec_phycard_imx27_common_init(void *fdt, int sdram) +extern char __dtb_imx27_phytec_phycard_s_rdk_bb_start[]; + +static void __noreturn phytec_phycard_imx27_start(void) +{ + void *fdt; + + fdt = __dtb_imx27_phytec_phycard_s_rdk_bb_start + get_runtime_offset(); + + imx27_barebox_entry(fdt); +} + +static void __noreturn phytec_phycard_imx27_load_nand(void) +{ + imx27_nand_load_image(); + phytec_phycard_imx27_start(); +} + +static noinline void __bare_init phytec_phycard_imx27_common_init(int sdram) { unsigned long r; @@ -92,7 +109,7 @@ /* Skip SDRAM initialization if we run from RAM */ r = get_pc(); if (r > 0xa0000000 && r < 0xc0000000) - imx27_barebox_entry(fdt); + phytec_phycard_imx27_start(); /* 399 MHz */ writel(IMX_PLL_PD(0) | @@ -117,29 +134,20 @@ sdram_init(sdram); - imx27_barebox_boot_nand_external(fdt); + imx27_nand_relocate_to_sdram(phytec_phycard_imx27_load_nand); + phytec_phycard_imx27_start(); } -extern char __dtb_imx27_phytec_phycard_s_rdk_bb_start[]; - ENTRY_FUNCTION(start_phytec_phycard_imx27_64mb, r0, r1, r2) { - void *fdt; - arm_setup_stack(MX27_IRAM_BASE_ADDR + MX27_IRAM_SIZE); - fdt = __dtb_imx27_phytec_phycard_s_rdk_bb_start + get_runtime_offset(); - - phytec_phycard_imx27_common_init(fdt, PHYCARD_MICRON_64MB); + phytec_phycard_imx27_common_init(PHYCARD_MICRON_64MB); } ENTRY_FUNCTION(start_phytec_phycard_imx27_128mb, r0, r1, r2) { - void *fdt; - arm_setup_stack(MX27_IRAM_BASE_ADDR + MX27_IRAM_SIZE); - fdt = __dtb_imx27_phytec_phycard_s_rdk_bb_start + get_runtime_offset(); - - phytec_phycard_imx27_common_init(fdt, PHYCARD_MICRON_128MB); + phytec_phycard_imx27_common_init(PHYCARD_MICRON_128MB); } diff --git a/arch/arm/boards/phytec-phycore-imx27/lowlevel.c b/arch/arm/boards/phytec-phycore-imx27/lowlevel.c index a9e296a..b3bebdb 100644 --- a/arch/arm/boards/phytec-phycore-imx27/lowlevel.c +++ b/arch/arm/boards/phytec-phycore-imx27/lowlevel.c @@ -33,7 +33,24 @@ #define ESDCTL0_VAL (ESDCTL0_SDE | ESDCTL0_ROW13 | ESDCTL0_COL10) -static void __bare_init __naked noinline phytec_phycorce_imx27_common_init(void *fdt) +extern char __dtb_imx27_phytec_phycore_rdk_start[]; + +static void __noreturn phytec_phycore_imx27_start(void) +{ + void *fdt; + + fdt = __dtb_imx27_phytec_phycore_rdk_start + get_runtime_offset(); + + imx27_barebox_entry(fdt); +} + +static void __noreturn phytec_phycore_imx27_load_nand(void) +{ + imx27_nand_load_image(); + phytec_phycore_imx27_start(); +} + +static void __bare_init noinline phytec_phycore_imx27_common_init(void) { uint32_t r; int i; @@ -49,7 +66,7 @@ /* Skip SDRAM initialization if we run from RAM */ r = get_pc(); if (r > 0xa0000000 && r < 0xb0000000) - goto out; + phytec_phycore_imx27_start(); /* re-program the PLL prior(!) starting the SDRAM controller */ writel(MPCTL0_VAL, MX27_CCM_BASE_ADDR + MX27_MPCTL0); @@ -93,22 +110,13 @@ ESDCTL0_BL | ESDCTL0_SMODE_NORMAL, MX27_ESDCTL_BASE_ADDR + IMX_ESDCTL0); - if (IS_ENABLED(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND)) - imx27_barebox_boot_nand_external(fdt); - -out: - imx27_barebox_entry(fdt); + imx27_nand_relocate_to_sdram(phytec_phycore_imx27_load_nand); + phytec_phycore_imx27_start(); } -extern char __dtb_imx27_phytec_phycore_rdk_start[]; - ENTRY_FUNCTION(start_phytec_phycore_imx27, r0, r1, r2) { - void *fdt; - arm_setup_stack(MX27_IRAM_BASE_ADDR + MX27_IRAM_SIZE); - fdt = __dtb_imx27_phytec_phycore_rdk_start + get_runtime_offset(); - - phytec_phycorce_imx27_common_init(fdt); + phytec_phycore_imx27_common_init(); } diff --git a/arch/arm/boards/phytec-phycore-imx31/lowlevel.c b/arch/arm/boards/phytec-phycore-imx31/lowlevel.c index b5f3339..98e1e87 100644 --- a/arch/arm/boards/phytec-phycore-imx31/lowlevel.c +++ b/arch/arm/boards/phytec-phycore-imx31/lowlevel.c @@ -127,7 +127,7 @@ #endif if (IS_ENABLED(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND)) - imx31_barebox_boot_nand_external(0); + imx31_barebox_boot_nand_external(); else imx31_barebox_entry(NULL); } diff --git a/arch/arm/boards/phytec-phycore-imx35/lowlevel.c b/arch/arm/boards/phytec-phycore-imx35/lowlevel.c index b80dafe..9768009 100644 --- a/arch/arm/boards/phytec-phycore-imx35/lowlevel.c +++ b/arch/arm/boards/phytec-phycore-imx35/lowlevel.c @@ -186,7 +186,7 @@ r |= 0x1 << 28; writel(r, MX35_CCM_BASE_ADDR + MX35_CCM_PDR4); - imx35_barebox_boot_nand_external(0); + imx35_barebox_boot_nand_external(); } out: diff --git a/arch/arm/cpu/lowlevel.S b/arch/arm/cpu/lowlevel.S index 3b52644..203a4af 100644 --- a/arch/arm/cpu/lowlevel.S +++ b/arch/arm/cpu/lowlevel.S @@ -57,8 +57,10 @@ bic r12, r12, #(CR_M | CR_C | CR_B) bic r12, r12, #(CR_S | CR_R | CR_V) +#ifndef CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND /* enable instruction cache */ orr r12, r12, #CR_I +#endif #if __LINUX_ARM_ARCH__ >= 6 orr r12, r12, #CR_U diff --git a/arch/arm/mach-imx/external-nand-boot.c b/arch/arm/mach-imx/external-nand-boot.c index c4d61aa..123589c 100644 --- a/arch/arm/mach-imx/external-nand-boot.c +++ b/arch/arm/mach-imx/external-nand-boot.c @@ -134,12 +134,13 @@ imx_nandboot_send_page(regs, v1, NFC_OUTPUT, pagesize_2k); } -static void __bare_init imx_nand_load_image(void *dest, int v1, int size, +static void __bare_init imx_nand_load_image(void *dest, int v1, void __iomem *base, int pagesize_2k) { u32 tmp, page, block, blocksize, pagesize, badblocks; int bbt = 0; void *regs, *spare0; + int size = *(uint32_t *)(dest + 0x2c); if (pagesize_2k) { pagesize = 2048; @@ -239,143 +240,188 @@ } } -static void BARE_INIT_FUNCTION(imx25_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) +void BARE_INIT_FUNCTION(imx25_nand_load_image)(void) { - imx_nand_load_image(dest, 0, size, base, pagesize_2k); -} + void *sdram = (void *)MX25_CSD0_BASE_ADDR; + void __iomem *nfc_base = IOMEM(MX25_NFC_BASE_ADDR); + bool pagesize_2k; -static void BARE_INIT_FUNCTION(imx27_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) -{ - imx_nand_load_image(dest, 1, size, base, pagesize_2k); -} - -static void BARE_INIT_FUNCTION(imx31_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) -{ - imx_nand_load_image(dest, 1, size, base, pagesize_2k); -} - -static void BARE_INIT_FUNCTION(imx35_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) -{ - imx_nand_load_image(dest, 0, size, base, pagesize_2k); -} - -static inline int imx25_pagesize_2k(void) -{ if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8)) - return 1; + pagesize_2k = true; else - return 0; + pagesize_2k = false; + + imx_nand_load_image(sdram, 0, nfc_base, pagesize_2k); } -static inline int imx27_pagesize_2k(void) +void BARE_INIT_FUNCTION(imx27_nand_load_image)(void) { + void *sdram = (void *)MX27_CSD0_BASE_ADDR; + void __iomem *nfc_base = IOMEM(MX27_NFC_BASE_ADDR); + bool pagesize_2k; + if (readl(MX27_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5)) - return 1; + pagesize_2k = true; else - return 0; + pagesize_2k = false; + + imx_nand_load_image(sdram, 1, nfc_base, pagesize_2k); } -static inline int imx31_pagesize_2k(void) +void BARE_INIT_FUNCTION(imx31_nand_load_image)(void) { + void *sdram = (void *)MX31_CSD0_BASE_ADDR; + void __iomem *nfc_base = IOMEM(MX31_NFC_BASE_ADDR); + bool pagesize_2k; + if (readl(MX31_CCM_BASE_ADDR + MX31_CCM_RCSR) & MX31_RCSR_NFMS) - return 1; + pagesize_2k = true; else - return 0; + pagesize_2k = false; + + imx_nand_load_image(sdram, 1, nfc_base, pagesize_2k); } -static inline int imx35_pagesize_2k(void) +void BARE_INIT_FUNCTION(imx35_nand_load_image)(void) { + void *sdram = (void *)MX35_CSD0_BASE_ADDR; + void __iomem *nfc_base = IOMEM(MX35_NFC_BASE_ADDR); + bool pagesize_2k; + if (readl(MX35_CCM_BASE_ADDR + MX35_CCM_RCSR) & (1 << 8)) - return 1; + pagesize_2k = true; else - return 0; + pagesize_2k = false; + + imx_nand_load_image(sdram, 0, nfc_base, pagesize_2k); } /* - * 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 - * NAND. In this case the booting is continued without loading an image from - * NAND. This function needs a stack to be set up. + * relocate_to_sdram - move ourselves out of NFC SRAM + * + * @nfc_base: base address of the NFC controller + * @sdram: SDRAM base address where we move ourselves to + * @fn: Function we continue with when running in SDRAM + * + * This function moves ourselves out of NFC SRAM to SDRAM. In case we a currently + * not running in NFC SRAM this function returns. If running in NFC SRAM, this + * function will not return, but call @fn instead. */ +static void BARE_INIT_FUNCTION(relocate_to_sdram)(unsigned long nfc_base, + unsigned long sdram, + void __noreturn (*fn)(void)) +{ + unsigned long __fn; + u32 r; + u32 *src, *trg; + int i; -#define DEFINE_EXTERNAL_NAND_ENTRY(soc) \ - \ -static void __noreturn BARE_INIT_FUNCTION(imx##soc##_boot_nand_external_cont) \ - (void *boarddata) \ -{ \ - unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \ - void *sdram = (void *)MX##soc##_CSD0_BASE_ADDR; \ - uint32_t image_size, r; \ - \ - image_size = *(uint32_t *)(sdram + 0x2c); \ - \ - r = get_cr(); \ - r |= CR_I; \ - set_cr(r); \ - \ - imx##soc##_nand_load_image(sdram, \ - image_size, \ - (void *)nfc_base, \ - imx##soc##_pagesize_2k()); \ - \ - imx##soc##_barebox_entry(boarddata); \ -} \ - \ -void __noreturn BARE_INIT_FUNCTION(imx##soc##_barebox_boot_nand_external) \ - (void *bd) \ -{ \ - unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \ - unsigned long sdram = MX##soc##_CSD0_BASE_ADDR; \ - unsigned long boarddata = (unsigned long)bd; \ - unsigned long __fn; \ - u32 r; \ - u32 *src, *trg; \ - int i; \ - void __noreturn (*fn)(void *); \ - \ - r = get_cr(); \ - r &= ~CR_I; \ - set_cr(r); \ - /* skip NAND boot if not running from NFC space */ \ - r = get_pc(); \ - if (r < nfc_base || r > nfc_base + 0x800) \ - imx##soc##_barebox_entry(bd); \ - \ - 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++; \ - \ - /* 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; \ - \ - fn = (void *)__fn; \ - \ - if (boarddata > nfc_base && boarddata < nfc_base + SZ_512K) { \ - boarddata &= SZ_512K - 1; \ - boarddata += sdram; \ - } \ - \ - fn((void *)boarddata); \ + /* skip NAND boot if not running from NFC space */ + r = get_pc(); + if (r < nfc_base || r > nfc_base + 0x800) + return; + + 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++; + + /* The next function we jump to */ + __fn = (unsigned long)fn; + /* mask out TEXT_BASE */ + __fn &= 0x7ff; + /* + * and add sdram base instead where we copied the initial + * binary above + */ + __fn += sdram; + + fn = (void *)__fn; + + fn(); } -DEFINE_EXTERNAL_NAND_ENTRY(25) -DEFINE_EXTERNAL_NAND_ENTRY(27) -DEFINE_EXTERNAL_NAND_ENTRY(31) -DEFINE_EXTERNAL_NAND_ENTRY(35) +void BARE_INIT_FUNCTION(imx25_nand_relocate_to_sdram)(void __noreturn (*fn)(void)) +{ + unsigned long nfc_base = MX25_NFC_BASE_ADDR; + unsigned long sdram = MX25_CSD0_BASE_ADDR; + + relocate_to_sdram(nfc_base, sdram, fn); +} + +static void __noreturn BARE_INIT_FUNCTION(imx25_boot_nand_external_cont)(void) +{ + imx25_nand_load_image(); + imx25_barebox_entry(NULL); +} + +void __noreturn BARE_INIT_FUNCTION(imx25_barebox_boot_nand_external)(void) +{ + imx25_nand_relocate_to_sdram(imx25_boot_nand_external_cont); + imx25_barebox_entry(NULL); +} + +void BARE_INIT_FUNCTION(imx27_nand_relocate_to_sdram)(void __noreturn (*fn)(void)) +{ + unsigned long nfc_base = MX27_NFC_BASE_ADDR; + unsigned long sdram = MX27_CSD0_BASE_ADDR; + + relocate_to_sdram(nfc_base, sdram, fn); +} + +static void __noreturn BARE_INIT_FUNCTION(imx27_boot_nand_external_cont)(void) +{ + imx27_nand_load_image(); + imx27_barebox_entry(NULL); +} + +void __noreturn BARE_INIT_FUNCTION(imx27_barebox_boot_nand_external)(void) +{ + imx27_nand_relocate_to_sdram(imx27_boot_nand_external_cont); + imx27_barebox_entry(NULL); +} + +void BARE_INIT_FUNCTION(imx31_nand_relocate_to_sdram)(void __noreturn (*fn)(void)) +{ + unsigned long nfc_base = MX31_NFC_BASE_ADDR; + unsigned long sdram = MX31_CSD0_BASE_ADDR; + + relocate_to_sdram(nfc_base, sdram, fn); +} + +static void __noreturn BARE_INIT_FUNCTION(imx31_boot_nand_external_cont)(void) +{ + imx31_nand_load_image(); + imx31_barebox_entry(NULL); +} + +void __noreturn BARE_INIT_FUNCTION(imx31_barebox_boot_nand_external)(void) +{ + imx31_nand_relocate_to_sdram(imx31_boot_nand_external_cont); + imx31_barebox_entry(NULL); +} + +void BARE_INIT_FUNCTION(imx35_nand_relocate_to_sdram)(void __noreturn (*fn)(void)) +{ + unsigned long nfc_base = MX35_NFC_BASE_ADDR; + unsigned long sdram = MX35_CSD0_BASE_ADDR; + + relocate_to_sdram(nfc_base, sdram, fn); +} + +static void __noreturn BARE_INIT_FUNCTION(imx35_boot_nand_external_cont)(void) +{ + imx35_nand_load_image(); + imx35_barebox_entry(NULL); +} + +void __noreturn BARE_INIT_FUNCTION(imx35_barebox_boot_nand_external)(void) +{ + imx35_nand_relocate_to_sdram(imx35_boot_nand_external_cont); + imx35_barebox_entry(NULL); +} diff --git a/arch/arm/mach-imx/include/mach/imx-nand.h b/arch/arm/mach-imx/include/mach/imx-nand.h index 0adba09..f34799a 100644 --- a/arch/arm/mach-imx/include/mach/imx-nand.h +++ b/arch/arm/mach-imx/include/mach/imx-nand.h @@ -3,11 +3,20 @@ #include -void imx21_barebox_boot_nand_external(void *boarddata); -void imx25_barebox_boot_nand_external(void *boarddata); -void imx27_barebox_boot_nand_external(void *boarddata); -void imx31_barebox_boot_nand_external(void *boarddata); -void imx35_barebox_boot_nand_external(void *boarddata); +void imx25_nand_load_image(void); +void imx27_nand_load_image(void); +void imx31_nand_load_image(void); +void imx35_nand_load_image(void); + +void imx25_nand_relocate_to_sdram(void __noreturn (*fn)(void)); +void imx27_nand_relocate_to_sdram(void __noreturn (*fn)(void)); +void imx31_nand_relocate_to_sdram(void __noreturn (*fn)(void)); +void imx35_nand_relocate_to_sdram(void __noreturn (*fn)(void)); + +void imx25_barebox_boot_nand_external(void); +void imx27_barebox_boot_nand_external(void); +void imx31_barebox_boot_nand_external(void); +void imx35_barebox_boot_nand_external(void); void imx_nand_set_layout(int writesize, int datawidth); struct imx_nand_platform_data {