summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx/external-nand-boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx/external-nand-boot.c')
-rw-r--r--arch/arm/mach-imx/external-nand-boot.c304
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);
+}