diff options
Diffstat (limited to 'arch/arm/mach-imx/external-nand-boot.c')
-rw-r--r-- | arch/arm/mach-imx/external-nand-boot.c | 304 |
1 files changed, 170 insertions, 134 deletions
diff --git a/arch/arm/mach-imx/external-nand-boot.c b/arch/arm/mach-imx/external-nand-boot.c index c4d61aa786..79cedbd68a 100644 --- a/arch/arm/mach-imx/external-nand-boot.c +++ b/arch/arm/mach-imx/external-nand-boot.c @@ -1,32 +1,22 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0-or-later #include <common.h> #include <init.h> #include <io.h> #include <linux/mtd/nand.h> +#include <linux/mtd/rawnand.h> #include <asm/cache.h> #include <asm/sections.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> -#include <mach/imx-nand.h> -#include <mach/esdctl.h> -#include <mach/generic.h> -#include <mach/imx21-regs.h> -#include <mach/imx25-regs.h> -#include <mach/imx27-regs.h> -#include <mach/imx31-regs.h> -#include <mach/imx35-regs.h> +#include <mach/imx/imx-nand.h> +#include <mach/imx/esdctl.h> +#include <mach/imx/generic.h> +#include <mach/imx/imx21-regs.h> +#include <mach/imx/imx25-regs.h> +#include <mach/imx/imx27-regs.h> +#include <mach/imx/imx31-regs.h> +#include <mach/imx/imx35-regs.h> #define BARE_INIT_FUNCTION(name) \ __section(.text_bare_init_##name) \ @@ -134,12 +124,13 @@ static noinline void __bare_init imx_nandboot_get_page(void *regs, int v1, 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 +230,188 @@ static void __bare_init imx_nand_load_image(void *dest, int v1, int size, } } -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; + + if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8)) + pagesize_2k = true; + else + pagesize_2k = false; + + imx_nand_load_image(sdram, 0, nfc_base, pagesize_2k); } -static void BARE_INIT_FUNCTION(imx27_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) +void BARE_INIT_FUNCTION(imx27_nand_load_image)(void) { - imx_nand_load_image(dest, 1, size, base, pagesize_2k); + 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)) + pagesize_2k = true; + else + pagesize_2k = false; + + imx_nand_load_image(sdram, 1, nfc_base, pagesize_2k); } -static void BARE_INIT_FUNCTION(imx31_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) +void BARE_INIT_FUNCTION(imx31_nand_load_image)(void) { - imx_nand_load_image(dest, 1, size, base, pagesize_2k); + 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) + pagesize_2k = true; + else + pagesize_2k = false; + + imx_nand_load_image(sdram, 1, nfc_base, pagesize_2k); } -static void BARE_INIT_FUNCTION(imx35_nand_load_image)(void *dest, int size, - void __iomem *base, int pagesize_2k) +void BARE_INIT_FUNCTION(imx35_nand_load_image)(void) { - imx_nand_load_image(dest, 0, size, base, pagesize_2k); + 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)) + pagesize_2k = true; + else + pagesize_2k = false; + + imx_nand_load_image(sdram, 0, nfc_base, pagesize_2k); } -static inline int imx25_pagesize_2k(void) +/* + * 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)) { - if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8)) - return 1; - else - return 0; + unsigned long __fn; + 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; + + 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(); } -static inline int imx27_pagesize_2k(void) +void BARE_INIT_FUNCTION(imx25_nand_relocate_to_sdram)(void __noreturn (*fn)(void)) { - if (readl(MX27_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5)) - return 1; - else - return 0; + unsigned long nfc_base = MX25_NFC_BASE_ADDR; + unsigned long sdram = MX25_CSD0_BASE_ADDR; + + relocate_to_sdram(nfc_base, sdram, fn); } -static inline int imx31_pagesize_2k(void) +static void __noreturn BARE_INIT_FUNCTION(imx25_boot_nand_external_cont)(void) { - if (readl(MX31_CCM_BASE_ADDR + MX31_CCM_RCSR) & MX31_RCSR_NFMS) - return 1; - else - return 0; + imx25_nand_load_image(); + imx25_barebox_entry(NULL); } -static inline int imx35_pagesize_2k(void) +void __noreturn BARE_INIT_FUNCTION(imx25_barebox_boot_nand_external)(void) { - if (readl(MX35_CCM_BASE_ADDR + MX35_CCM_RCSR) & (1 << 8)) - return 1; - else - return 0; + imx25_nand_relocate_to_sdram(imx25_boot_nand_external_cont); + imx25_barebox_entry(NULL); } -/* - * 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. - */ +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); +} -#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); \ +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); } -DEFINE_EXTERNAL_NAND_ENTRY(25) -DEFINE_EXTERNAL_NAND_ENTRY(27) -DEFINE_EXTERNAL_NAND_ENTRY(31) -DEFINE_EXTERNAL_NAND_ENTRY(35) +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); +} |