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.c290
1 files changed, 141 insertions, 149 deletions
diff --git a/arch/arm/mach-imx/external-nand-boot.c b/arch/arm/mach-imx/external-nand-boot.c
index 1af46b78ea..fe933aa3a9 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;
@@ -91,12 +95,12 @@ static void __bare_init imx_nandboot_nfc_addr(void *regs, u32 offs, int pagesize
}
}
-static void __bare_init imx_nandboot_send_page(void *regs,
+static void __bare_init imx_nandboot_send_page(void *regs, int v1,
unsigned int ops, int pagesize_2k)
{
int bufs, i;
- if (nfc_is_v1() && pagesize_2k)
+ if (v1 && pagesize_2k)
bufs = 4;
else
bufs = 1;
@@ -122,15 +126,15 @@ static void __bare_init __memcpy32(void *trg, const void *src, int size)
*t++ = *s++;
}
-static noinline void __bare_init imx_nandboot_get_page(void *regs,
+static noinline void __bare_init imx_nandboot_get_page(void *regs, int v1,
u32 offs, int pagesize_2k)
{
imx_nandboot_send_cmd(regs, NAND_CMD_READ0);
imx_nandboot_nfc_addr(regs, offs, pagesize_2k);
- imx_nandboot_send_page(regs, NFC_OUTPUT, pagesize_2k);
+ imx_nandboot_send_page(regs, v1, NFC_OUTPUT, pagesize_2k);
}
-void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
+void __bare_init imx_nand_load_image(void *dest, int v1, int size, void __iomem *base,
int pagesize_2k)
{
u32 tmp, page, block, blocksize, pagesize, badblocks;
@@ -145,12 +149,12 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
blocksize = 16 * 1024;
}
- if (nfc_is_v21()) {
- regs = base + 0x1e00;
- spare0 = base + 0x1000;
- } else if (nfc_is_v1()) {
+ if (v1) {
regs = base + 0xe00;
spare0 = base + 0x800;
+ } else {
+ regs = base + 0x1e00;
+ spare0 = base + 0x1000;
}
imx_nandboot_send_cmd(regs, NAND_CMD_RESET);
@@ -164,13 +168,13 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
tmp = readw(regs + NFC_V1_V2_CONFIG1);
tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
- if (nfc_is_v21())
+ if (!v1)
/* currently no support for 218 byte OOB with stronger ECC */
tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
tmp &= ~(NFC_V1_V2_CONFIG1_SP_EN | NFC_V1_V2_CONFIG1_INT_MSK);
writew(tmp, regs + NFC_V1_V2_CONFIG1);
- if (nfc_is_v21()) {
+ if (!v1) {
if (pagesize_2k)
writew(NFC_V2_SPAS_SPARESIZE(64), regs + NFC_V2_SPAS);
else
@@ -192,7 +196,7 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
while (1) {
page = 0;
- imx_nandboot_get_page(regs, block * blocksize +
+ imx_nandboot_get_page(regs, v1, block * blocksize +
page * pagesize, pagesize_2k);
if (bbt) {
@@ -219,7 +223,7 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
block * blocksize +
page * pagesize);
if (page)
- imx_nandboot_get_page(regs, block * blocksize +
+ imx_nandboot_get_page(regs, v1, block * blocksize +
page * pagesize, pagesize_2k);
page++;
@@ -235,164 +239,152 @@ 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)
+void BARE_INIT_FUNCTION(imx21_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- flush_icache();
-
- __asm__ __volatile__ (
- "sub lr, lr, %0;"
- "mov pc, lr;" : : "r"(offset)
- );
+ imx_nand_load_image(dest, 1, size, base, pagesize_2k);
}
-/*
- * 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)
+void BARE_INIT_FUNCTION(imx25_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- 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;
+ imx_nand_load_image(dest, 0, size, base, pagesize_2k);
}
-#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
- * NAND. In this case the booting is continued without loading an image from
- * NAND. This function needs a stack to be set up.
- */
-#ifdef BROKEN
-BARE_INIT_FUNCTION(imx21_barebox_boot_nand_external)(void)
+void BARE_INIT_FUNCTION(imx27_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- unsigned long nfc_base = MX21_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX21_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
-
- /* This function doesn't exist yet */
- imx21_barebox_entry(0);
+ imx_nand_load_image(dest, 1, size, base, pagesize_2k);
}
-#endif
-BARE_INIT_FUNCTION(imx25_barebox_boot_nand_external)(void)
+void BARE_INIT_FUNCTION(imx31_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- unsigned long nfc_base = MX25_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
-
- imx25_barebox_entry(0);
+ imx_nand_load_image(dest, 1, size, base, pagesize_2k);
}
-BARE_INIT_FUNCTION(imx27_barebox_boot_nand_external)(void)
+void BARE_INIT_FUNCTION(imx35_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- unsigned long nfc_base = MX27_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX27_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
-
- imx27_barebox_entry(0);
+ imx_nand_load_image(dest, 0, size, base, pagesize_2k);
}
-BARE_INIT_FUNCTION(imx31_barebox_boot_nand_external)(void)
+static inline int imx21_pagesize_2k(void)
{
- unsigned long nfc_base = MX31_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX31_CCM_BASE_ADDR + MX31_CCM_RCSR) & MX31_RCSR_NFMS)
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
+ if (readl(MX21_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
+ return 1;
+ else
+ return 0;
+}
- imx31_barebox_entry(0);
+static inline int imx25_pagesize_2k(void)
+{
+ if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8))
+ return 1;
+ else
+ return 0;
}
-BARE_INIT_FUNCTION(imx35_barebox_boot_nand_external)(void)
+static inline int imx27_pagesize_2k(void)
{
- unsigned long nfc_base = MX35_NFC_BASE_ADDR;
- int pagesize_2k;
+ if (readl(MX27_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
+ return 1;
+ else
+ return 0;
+}
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
+static inline int imx31_pagesize_2k(void)
+{
+ if (readl(MX31_CCM_BASE_ADDR + MX31_CCM_RCSR) & MX31_RCSR_NFMS)
+ return 1;
+ else
+ return 0;
+}
- if (readl(MX35_CCM_BASE_ADDR + MX35_CCM_RCSR) & (1 << 8))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
+static inline int imx35_pagesize_2k(void)
+{
+ if (readl(MX35_CCM_BASE_ADDR + MX35_CCM_RCSR) & (1 << 8))
+ return 1;
+ else
+ return 0;
+}
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)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.
+ */
- imx35_barebox_entry(0);
+#define DEFINE_EXTERNAL_NAND_ENTRY(soc) \
+ \
+void __noreturn BARE_INIT_FUNCTION(imx##soc##_boot_nand_external_cont) \
+ (uint32_t boarddata) \
+{ \
+ unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \
+ void *sdram = (void *)MX##soc##_CSD0_BASE_ADDR; \
+ uint32_t image_size; \
+ \
+ image_size = *(uint32_t *)(sdram + 0x2c); \
+ \
+ 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) \
+ (uint32_t boarddata) \
+{ \
+ 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)(uint32_t); \
+ \
+ /* skip NAND boot if not running from NFC space */ \
+ r = get_pc(); \
+ if (r < nfc_base || r > nfc_base + 0x800) \
+ imx##soc##_barebox_entry(boarddata); \
+ \
+ 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(boarddata); \
}
+
+#ifdef BROKEN
+DEFINE_EXTERNAL_NAND_ENTRY(21)
+#endif
+DEFINE_EXTERNAL_NAND_ENTRY(25)
+DEFINE_EXTERNAL_NAND_ENTRY(27)
+DEFINE_EXTERNAL_NAND_ENTRY(31)
+DEFINE_EXTERNAL_NAND_ENTRY(35)