[U-Boot-Users] [PATCH 2/2] NAND boot: MPC8313ERDB support

Scott Wood scottwood at freescale.com
Tue Aug 5 00:46:01 CEST 2008


Note that with older board revisions, NAND boot may only work after a
power-on reset, and not after a warm reset.  I suspect there are hardware
issues involved.

I don't have a newer board to test on, though previous implementations
have been reported to work on boards with a 33MHz crystal (which current
revisions have).  If you have such a board, please let me know if it
works after a warm reset.

Signed-off-by: Scott Wood <scottwood at freescale.com>
---
Applied to u-boot-nand-flash/testing.

 Makefile                                        |   10 ++-
 board/freescale/mpc8313erdb/config.mk           |    6 +
 board/freescale/mpc8313erdb/mpc8313erdb.c       |   32 +++++
 board/freescale/mpc8313erdb/sdram.c             |    5 +-
 cpu/mpc83xx/nand_init.c                         |  112 +++++++++++++++++
 cpu/mpc83xx/start.S                             |  152 +++++++----------------
 include/configs/MPC8313ERDB.h                   |   82 ++++++++++---
 include/mpc83xx.h                               |    2 +
 include/nand.h                                  |    2 +
 lib_ppc/time.c                                  |    4 +-
 nand_spl/board/freescale/mpc8313erdb/Makefile   |  101 +++++++++++++++
 nand_spl/board/freescale/mpc8313erdb/u-boot.lds |   52 ++++++++
 nand_spl/nand_boot.c                            |    4 +-
 nand_spl/nand_boot_fsl_elbc.c                   |  150 ++++++++++++++++++++++
 14 files changed, 585 insertions(+), 129 deletions(-)
 create mode 100644 cpu/mpc83xx/nand_init.c
 create mode 100644 nand_spl/board/freescale/mpc8313erdb/Makefile
 create mode 100644 nand_spl/board/freescale/mpc8313erdb/u-boot.lds
 create mode 100644 nand_spl/nand_boot_fsl_elbc.c

diff --git a/Makefile b/Makefile
index 4875c89..cb8c0f5 100644
--- a/Makefile
+++ b/Makefile
@@ -1997,8 +1997,11 @@ TASREG_config :		unconfig
 #########################################################################
 
 MPC8313ERDB_33_config \
-MPC8313ERDB_66_config: unconfig
+MPC8313ERDB_66_config \
+MPC8313ERDB_NAND_33_config \
+MPC8313ERDB_NAND_66_config: unconfig
 	@mkdir -p $(obj)include
+	@mkdir -p $(obj)board/freescale/mpc8313erdb
 	@if [ "$(findstring _33_,$@)" ] ; then \
 		$(XECHO) -n "...33M ..." ; \
 		echo "#define CFG_33MHZ" >>$(obj)include/config.h ; \
@@ -2006,6 +2009,11 @@ MPC8313ERDB_66_config: unconfig
 	if [ "$(findstring _66_,$@)" ] ; then \
 		$(XECHO) -n "...66M..." ; \
 		echo "#define CFG_66MHZ" >>$(obj)include/config.h ; \
+	fi ; \
+	if [ "$(findstring _NAND_,$@)" ] ; then \
+		$(XECHO) -n "...NAND..." ; \
+		echo "TEXT_BASE = 0x00100000" > $(obj)/board/freescale/mpc8313erdb/config.tmp ; \
+		echo "#define CONFIG_NAND_U_BOOT" >>$(obj)include/config.h ; \
 	fi ;
 	@$(MKCONFIG) -a MPC8313ERDB ppc mpc83xx mpc8313erdb freescale
 
diff --git a/board/freescale/mpc8313erdb/config.mk b/board/freescale/mpc8313erdb/config.mk
index f768264..fd72a14 100644
--- a/board/freescale/mpc8313erdb/config.mk
+++ b/board/freescale/mpc8313erdb/config.mk
@@ -1 +1,7 @@
+ifndef NAND_SPL
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+endif
+
+ifndef TEXT_BASE
 TEXT_BASE = 0xFE000000
+endif
diff --git a/board/freescale/mpc8313erdb/mpc8313erdb.c b/board/freescale/mpc8313erdb/mpc8313erdb.c
index 7cbdb7b..ebb703d 100644
--- a/board/freescale/mpc8313erdb/mpc8313erdb.c
+++ b/board/freescale/mpc8313erdb/mpc8313erdb.c
@@ -29,6 +29,8 @@
 #include <pci.h>
 #include <mpc83xx.h>
 #include <vsc7385.h>
+#include <ns16550.h>
+#include <nand.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -50,6 +52,7 @@ int checkboard(void)
 	return 0;
 }
 
+#ifndef CONFIG_NAND_SPL
 static struct pci_region pci_regions[] = {
 	{
 		bus_start: CFG_PCI1_MEM_BASE,
@@ -128,3 +131,32 @@ void ft_board_setup(void *blob, bd_t *bd)
 #endif
 }
 #endif
+#else /* CONFIG_NAND_SPL */
+void board_init_f(ulong bootflag)
+{
+	board_early_init_f();
+	NS16550_init((NS16550_t)(CFG_IMMR + 0x4500),
+	             CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE);
+	puts("NAND boot... ");
+	init_timebase();
+	initdram(0);
+	relocate_code(CFG_NAND_U_BOOT_RELOC + 0x10000, (gd_t *)gd,
+	              CFG_NAND_U_BOOT_RELOC);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+	nand_boot();
+}
+
+void putc(char c)
+{
+	if (gd->flags & GD_FLG_SILENT)
+		return;
+
+	if (c == '\n')
+		NS16550_putc((NS16550_t)(CFG_IMMR + 0x4500), '\r');
+
+	NS16550_putc((NS16550_t)(CFG_IMMR + 0x4500), c);
+}
+#endif
diff --git a/board/freescale/mpc8313erdb/sdram.c b/board/freescale/mpc8313erdb/sdram.c
index afd8b9d..3a6347f 100644
--- a/board/freescale/mpc8313erdb/sdram.c
+++ b/board/freescale/mpc8313erdb/sdram.c
@@ -58,8 +58,10 @@ static void resume_from_sleep(void)
  */
 static long fixed_sdram(void)
 {
-	volatile immap_t *im = (volatile immap_t *)CFG_IMMR;
 	u32 msize = CFG_DDR_SIZE * 1024 * 1024;
+
+#ifndef CFG_RAMBOOT
+	volatile immap_t *im = (volatile immap_t *)CFG_IMMR;
 	u32 msize_log2 = __ilog2(msize);
 
 	im->sysconf.ddrlaw[0].bar = CFG_DDR_SDRAM_BASE >> 12;
@@ -100,6 +102,7 @@ static long fixed_sdram(void)
 
 	/* enable DDR controller */
 	im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN;
+#endif
 
 	return msize;
 }
diff --git a/cpu/mpc83xx/nand_init.c b/cpu/mpc83xx/nand_init.c
new file mode 100644
index 0000000..e92f230
--- /dev/null
+++ b/cpu/mpc83xx/nand_init.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+	int i;
+
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
+
+	/* Clear initial global data */
+	for (i = 0; i < sizeof(gd_t); i++)
+		((char *)gd)[i] = 0;
+
+	/* system performance tweaking */
+
+#ifdef CFG_ACR_PIPE_DEP
+	/* Arbiter pipeline depth */
+	im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
+			  (CFG_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
+#endif
+
+#ifdef CFG_ACR_RPTCNT
+	/* Arbiter repeat count */
+	im->arbiter.acr = (im->arbiter.acr & ~(ACR_RPTCNT)) |
+			  (CFG_ACR_RPTCNT << ACR_RPTCNT_SHIFT);
+#endif
+
+#ifdef CFG_SPCR_OPT
+	/* Optimize transactions between CSB and other devices */
+	im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_OPT) |
+			   (CFG_SPCR_OPT << SPCR_OPT_SHIFT);
+#endif
+
+	/* Enable Time Base & Decrimenter (so we will have udelay()) */
+	im->sysconf.spcr |= SPCR_TBEN;
+
+	/* DDR control driver register */
+#ifdef CFG_DDRCDR
+	im->sysconf.ddrcdr = CFG_DDRCDR;
+#endif
+	/* Output buffer impedance register */
+#ifdef CFG_OBIR
+	im->sysconf.obir = CFG_OBIR;
+#endif
+
+	/*
+	 * Memory Controller:
+	 */
+
+	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+	 * addresses - these have to be modified later when FLASH size
+	 * has been determined
+	 */
+
+#if defined(CFG_NAND_BR_PRELIM)  \
+	&& defined(CFG_NAND_OR_PRELIM) \
+	&& defined(CFG_NAND_LBLAWBAR_PRELIM) \
+	&& defined(CFG_NAND_LBLAWAR_PRELIM)
+	im->lbus.bank[0].br = CFG_NAND_BR_PRELIM;
+	im->lbus.bank[0].or = CFG_NAND_OR_PRELIM;
+	im->sysconf.lblaw[0].bar = CFG_NAND_LBLAWBAR_PRELIM;
+	im->sysconf.lblaw[0].ar = CFG_NAND_LBLAWAR_PRELIM;
+#else
+#error CFG_NAND_BR_PRELIM, CFG_NAND_OR_PRELIM, CFG_NAND_LBLAWBAR_PRELIM & CFG_NAND_LBLAWAR_PRELIM must be defined
+#endif
+}
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk(void)
+{
+	return (gd->bus_clk + 3L) / 4L;
+}
+
+void puts(const char *str)
+{
+	while (*str)
+		putc(*str++);
+}
diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S
index c182174..16ed494 100644
--- a/cpu/mpc83xx/start.S
+++ b/cpu/mpc83xx/start.S
@@ -2,7 +2,7 @@
  * Copyright (C) 1998  Dan Malek <dmalek at jlc.net>
  * Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
  * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd at denx.de>
- * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006, 2008.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -57,6 +57,10 @@
 #define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
 #endif
 
+#if !defined(CONFIG_NAND_SPL) && !defined(CFG_RAMBOOT)
+#define CFG_FLASHBOOT
+#endif
+
 /*
  * Set up GOT: Global Offset Table
  *
@@ -64,16 +68,16 @@
  */
 	START_GOT
 	GOT_ENTRY(_GOT2_TABLE_)
-	GOT_ENTRY(_FIXUP_TABLE_)
+	GOT_ENTRY(__bss_start)
+	GOT_ENTRY(_end)
 
+#ifndef CONFIG_NAND_SPL
+	GOT_ENTRY(_FIXUP_TABLE_)
 	GOT_ENTRY(_start)
 	GOT_ENTRY(_start_of_vectors)
 	GOT_ENTRY(_end_of_vectors)
 	GOT_ENTRY(transfer_to_handler)
-
-	GOT_ENTRY(__init_end)
-	GOT_ENTRY(_end)
-	GOT_ENTRY(__bss_start)
+#endif
 	END_GOT
 
 /*
@@ -165,7 +169,7 @@ boot_warm: /* time t 5 */
 
 	bl	init_e300_core
 
-#ifndef CFG_RAMBOOT
+#ifdef CFG_FLASHBOOT
 
 	/* Inflate flash location so it appears everywhere, calculate */
 	/* the absolute address in final location of the FLASH, jump  */
@@ -181,7 +185,7 @@ in_flash:
 #if 1 /* Remapping flash with LAW0. */
 	bl remap_flash_by_law0
 #endif
-#endif	/* CFG_RAMBOOT */
+#endif	/* CFG_FLASHBOOT */
 
 	/* setup the bats */
 	bl	setup_bats
@@ -239,6 +243,7 @@ in_flash:
 	/* run 1st part of board init code (in Flash)*/
 	bl	board_init_f
 
+#ifndef CONFIG_NAND_SPL
 /*
  * Vector Table
  */
@@ -428,6 +433,7 @@ int_return:
 	lwz	r1,GPR1(r1)
 	SYNC
 	rfi
+#endif /* !CONFIG_NAND_SPL */
 
 /*
  * This code initialises the E300 processor core
@@ -496,88 +502,10 @@ init_e300_core: /* time t 10 */
 	SYNC
 	mtspr	HID2, r3
 
-	/* clear all BAT's					*/
-	/*----------------------------------*/
-
-	xor	r0, r0, r0
-	mtspr	DBAT0U, r0
-	mtspr	DBAT0L, r0
-	mtspr	DBAT1U, r0
-	mtspr	DBAT1L, r0
-	mtspr	DBAT2U, r0
-	mtspr	DBAT2L, r0
-	mtspr	DBAT3U, r0
-	mtspr	DBAT3L, r0
-	mtspr	IBAT0U, r0
-	mtspr	IBAT0L, r0
-	mtspr	IBAT1U, r0
-	mtspr	IBAT1L, r0
-	mtspr	IBAT2U, r0
-	mtspr	IBAT2L, r0
-	mtspr	IBAT3U, r0
-	mtspr	IBAT3L, r0
-	SYNC
-
-	/* invalidate all tlb's
-	 *
-	 * From the 603e User Manual: "The 603e provides the ability to
-	 * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
-	 * instruction invalidates the TLB entry indexed by the EA, and
-	 * operates on both the instruction and data TLBs simultaneously
-	 * invalidating four TLB entries (both sets in each TLB). The
-	 * index corresponds to bits 15-19 of the EA. To invalidate all
-	 * entries within both TLBs, 32 tlbie instructions should be
-	 * issued, incrementing this field by one each time."
-	 *
-	 * "Note that the tlbia instruction is not implemented on the
-	 * 603e."
-	 *
-	 * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
-	 * incrementing by 0x1000 each time. The code below is sort of
-	 * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
-	 *
-	 */
-
-	li	r3, 32
-	mtctr	r3
-	li	r3, 0
-1:	tlbie	r3
-	addi	r3, r3, 0x1000
-	bdnz	1b
-	SYNC
-
 	/* Done!						*/
 	/*------------------------------*/
 	blr
 
-	.globl	invalidate_bats
-invalidate_bats:
-	/* invalidate BATs */
-	mtspr	IBAT0U, r0
-	mtspr	IBAT1U, r0
-	mtspr	IBAT2U, r0
-	mtspr	IBAT3U, r0
-#ifdef CONFIG_HIGH_BATS
-	mtspr   IBAT4U, r0
-	mtspr   IBAT5U, r0
-	mtspr   IBAT6U, r0
-	mtspr   IBAT7U, r0
-#endif
-	isync
-	mtspr	DBAT0U, r0
-	mtspr	DBAT1U, r0
-	mtspr	DBAT2U, r0
-	mtspr	DBAT3U, r0
-#ifdef CONFIG_HIGH_BATS
-	mtspr   DBAT4U, r0
-	mtspr   DBAT5U, r0
-	mtspr   DBAT6U, r0
-	mtspr   DBAT7U, r0
-#endif
-	isync
-	sync
-	blr
-
 	/* setup_bats - set them up to some initial state */
 	.globl	setup_bats
 setup_bats:
@@ -590,7 +518,6 @@ setup_bats:
 	ori	r3, r3, CFG_IBAT0U at l
 	mtspr	IBAT0L, r4
 	mtspr	IBAT0U, r3
-	isync
 
 	/* DBAT 0 */
 	addis	r4, r0, CFG_DBAT0L at h
@@ -599,7 +526,6 @@ setup_bats:
 	ori	r3, r3, CFG_DBAT0U at l
 	mtspr	DBAT0L, r4
 	mtspr	DBAT0U, r3
-	isync
 
 	/* IBAT 1 */
 	addis	r4, r0, CFG_IBAT1L at h
@@ -608,7 +534,6 @@ setup_bats:
 	ori	r3, r3, CFG_IBAT1U at l
 	mtspr	IBAT1L, r4
 	mtspr	IBAT1U, r3
-	isync
 
 	/* DBAT 1 */
 	addis	r4, r0, CFG_DBAT1L at h
@@ -617,7 +542,6 @@ setup_bats:
 	ori	r3, r3, CFG_DBAT1U at l
 	mtspr	DBAT1L, r4
 	mtspr	DBAT1U, r3
-	isync
 
 	/* IBAT 2 */
 	addis	r4, r0, CFG_IBAT2L at h
@@ -626,7 +550,6 @@ setup_bats:
 	ori	r3, r3, CFG_IBAT2U at l
 	mtspr	IBAT2L, r4
 	mtspr	IBAT2U, r3
-	isync
 
 	/* DBAT 2 */
 	addis	r4, r0, CFG_DBAT2L at h
@@ -635,7 +558,6 @@ setup_bats:
 	ori	r3, r3, CFG_DBAT2U at l
 	mtspr	DBAT2L, r4
 	mtspr	DBAT2U, r3
-	isync
 
 	/* IBAT 3 */
 	addis	r4, r0, CFG_IBAT3L at h
@@ -644,7 +566,6 @@ setup_bats:
 	ori	r3, r3, CFG_IBAT3U at l
 	mtspr	IBAT3L, r4
 	mtspr	IBAT3U, r3
-	isync
 
 	/* DBAT 3 */
 	addis	r4, r0, CFG_DBAT3L at h
@@ -653,7 +574,6 @@ setup_bats:
 	ori	r3, r3, CFG_DBAT3U at l
 	mtspr	DBAT3L, r4
 	mtspr	DBAT3U, r3
-	isync
 
 #ifdef CONFIG_HIGH_BATS
 	/* IBAT 4 */
@@ -663,7 +583,6 @@ setup_bats:
 	ori     r3, r3, CFG_IBAT4U at l
 	mtspr   IBAT4L, r4
 	mtspr   IBAT4U, r3
-	isync
 
 	/* DBAT 4 */
 	addis   r4, r0, CFG_DBAT4L at h
@@ -672,7 +591,6 @@ setup_bats:
 	ori     r3, r3, CFG_DBAT4U at l
 	mtspr   DBAT4L, r4
 	mtspr   DBAT4U, r3
-	isync
 
 	/* IBAT 5 */
 	addis   r4, r0, CFG_IBAT5L at h
@@ -681,7 +599,6 @@ setup_bats:
 	ori     r3, r3, CFG_IBAT5U at l
 	mtspr   IBAT5L, r4
 	mtspr   IBAT5U, r3
-	isync
 
 	/* DBAT 5 */
 	addis   r4, r0, CFG_DBAT5L at h
@@ -690,7 +607,6 @@ setup_bats:
 	ori     r3, r3, CFG_DBAT5U at l
 	mtspr   DBAT5L, r4
 	mtspr   DBAT5U, r3
-	isync
 
 	/* IBAT 6 */
 	addis   r4, r0, CFG_IBAT6L at h
@@ -699,7 +615,6 @@ setup_bats:
 	ori     r3, r3, CFG_IBAT6U at l
 	mtspr   IBAT6L, r4
 	mtspr   IBAT6U, r3
-	isync
 
 	/* DBAT 6 */
 	addis   r4, r0, CFG_DBAT6L at h
@@ -708,7 +623,6 @@ setup_bats:
 	ori     r3, r3, CFG_DBAT6U at l
 	mtspr   DBAT6L, r4
 	mtspr   DBAT6U, r3
-	isync
 
 	/* IBAT 7 */
 	addis   r4, r0, CFG_IBAT7L at h
@@ -717,7 +631,6 @@ setup_bats:
 	ori     r3, r3, CFG_IBAT7U at l
 	mtspr   IBAT7L, r4
 	mtspr   IBAT7U, r3
-	isync
 
 	/* DBAT 7 */
 	addis   r4, r0, CFG_DBAT7L at h
@@ -726,12 +639,28 @@ setup_bats:
 	ori     r3, r3, CFG_DBAT7U at l
 	mtspr   DBAT7L, r4
 	mtspr   DBAT7U, r3
-	isync
 #endif
 
-	/* Invalidate TLBs.
-	 * -> for (val = 0; val < 0x20000; val+=0x1000)
-	 * ->   tlbie(val);
+	isync
+
+	/* invalidate all tlb's
+	 *
+	 * From the 603e User Manual: "The 603e provides the ability to
+	 * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
+	 * instruction invalidates the TLB entry indexed by the EA, and
+	 * operates on both the instruction and data TLBs simultaneously
+	 * invalidating four TLB entries (both sets in each TLB). The
+	 * index corresponds to bits 15-19 of the EA. To invalidate all
+	 * entries within both TLBs, 32 tlbie instructions should be
+	 * issued, incrementing this field by one each time."
+	 *
+	 * "Note that the tlbia instruction is not implemented on the
+	 * 603e."
+	 *
+	 * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
+	 * incrementing by 0x1000 each time. The code below is sort of
+	 * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
+	 *
 	 */
 	lis	r3, 0
 	lis	r5, 2
@@ -874,7 +803,7 @@ relocate_code:
 	mr	r3,  r5				/* Destination Address */
 	lis	r4, CFG_MONITOR_BASE at h		/* Source      Address */
 	ori	r4, r4, CFG_MONITOR_BASE at l
-	lwz	r5, GOT(__init_end)
+	lwz	r5, GOT(__bss_start)
 	sub	r5, r5, r4
 	li	r6, CFG_CACHELINE_SIZE		/* Cache Line Size */
 
@@ -987,6 +916,7 @@ in_ram:
 	stw	r0,0(r3)
 	bdnz	1b
 
+#ifndef CONFIG_NAND_SPL
 	/*
 	 * Now adjust the fixups and the pointers to the fixups
 	 * in case we need to move ourselves again.
@@ -1004,6 +934,8 @@ in_ram:
 	stw	r0,0(r4)
 	bdnz	3b
 4:
+#endif
+
 clear_bss:
 	/*
 	 * Now clear BSS segment
@@ -1037,6 +969,7 @@ clear_bss:
 	mr	r4, r10		/* Destination Address		*/
 	bl	board_init_r
 
+#ifndef CONFIG_NAND_SPL
 	/*
 	 * Copy exception vector code to low memory
 	 *
@@ -1119,6 +1052,7 @@ trap_reloc:
 	stw	r0, 4(r7)
 
 	blr
+#endif /* !CONFIG_NAND_SPL */
 
 #ifdef CFG_INIT_RAM_LOCK
 lock_ram_in_cache:
@@ -1142,6 +1076,7 @@ lock_ram_in_cache:
 	sync
 	blr
 
+#ifndef CONFIG_NAND_SPL
 .globl unlock_ram_in_cache
 unlock_ram_in_cache:
 	/* invalidate the INIT_RAM section */
@@ -1165,8 +1100,10 @@ unlock_ram_in_cache:
 	mtspr	HID0, r3		/* no invalidate, unlock */
 	sync
 	blr
-#endif
+#endif /* !CONFIG_NAND_SPL */
+#endif /* CFG_INIT_RAM_LOCK */
 
+#ifdef CFG_FLASHBOOT
 map_flash_by_law1:
 	/* When booting from ROM (Flash or EPROM), clear the  */
 	/* Address Mask in OR0 so ROM appears everywhere      */
@@ -1245,3 +1182,4 @@ remap_flash_by_law0:
 	stw r4, LBLAWBAR1(r3)
 	stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
 	blr
+#endif /* CFG_FLASHBOOT */
diff --git a/include/configs/MPC8313ERDB.h b/include/configs/MPC8313ERDB.h
index 3a644d3..37f8cff 100644
--- a/include/configs/MPC8313ERDB.h
+++ b/include/configs/MPC8313ERDB.h
@@ -63,6 +63,10 @@
 
 #define CFG_IMMR		0xE0000000
 
+#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#define CONFIG_DEFAULT_IMMR 	CFG_IMMR
+#endif
+
 #define CFG_MEMTEST_START	0x00001000
 #define CFG_MEMTEST_END		0x07f00000
 
@@ -173,10 +177,10 @@
 #define CFG_FLASH_EMPTY_INFO			/* display empty sectors */
 #define CFG_FLASH_USE_BUFFER_WRITE		/* buffer up multiple bytes */
 
-#define CFG_BR0_PRELIM		(CFG_FLASH_BASE |	/* flash Base address */ \
+#define CFG_NOR_BR_PRELIM	(CFG_FLASH_BASE |	/* flash Base address */ \
 				(2 << BR_PS_SHIFT) |	/* 16 bit port size */ \
 				BR_V)			/* valid */
-#define CFG_OR0_PRELIM		( 0xFF000000		/* 16 MByte */ \
+#define CFG_NOR_OR_PRELIM	( 0xFF800000		/* 8 MByte */ \
 				| OR_GPCM_XACS \
 				| OR_GPCM_SCY_9 \
 				| OR_GPCM_EHTR \
@@ -193,7 +197,7 @@
 
 #define CFG_MONITOR_BASE	TEXT_BASE	/* start of monitor */
 
-#if (CFG_MONITOR_BASE < CFG_FLASH_BASE)
+#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) && !defined(CONFIG_NAND_SPL)
 #define CFG_RAMBOOT
 #endif
 
@@ -220,19 +224,31 @@
 #define CFG_LBC_MRTPR	0x20000000  /*TODO */	/* LB refresh timer prescal, 266MHz/32 */
 
 /* drivers/mtd/nand/nand.c */
-#define CFG_NAND_BASE		0xE2800000	/* 0xF0000000 */
+#ifdef CONFIG_NAND_SPL
+#define CFG_NAND_BASE		0xFFF00000
+#else
+#define CFG_NAND_BASE		0xE2800000
+#endif
+
 #define CFG_MAX_NAND_DEVICE	1
 #define NAND_MAX_CHIPS		1
 #define CONFIG_MTD_NAND_VERIFY_WRITE
 #define CONFIG_CMD_NAND 1
 #define CONFIG_NAND_FSL_ELBC 1
+#define CFG_NAND_BLOCK_SIZE 16384
+
+#define CFG_NAND_U_BOOT_SIZE  (512 << 10)
+#define CFG_NAND_U_BOOT_DST   0x00100000
+#define CFG_NAND_U_BOOT_START 0x00100100
+#define CFG_NAND_U_BOOT_OFFS  16384
+#define CFG_NAND_U_BOOT_RELOC 0x00010000
 
-#define CFG_BR1_PRELIM		( CFG_NAND_BASE \
+#define CFG_NAND_BR_PRELIM 	( CFG_NAND_BASE \
 				| (2<<BR_DECC_SHIFT)	/* Use HW ECC */ \
 				| BR_PS_8		/* Port Size = 8 bit */ \
 				| BR_MS_FCM		/* MSEL = FCM */ \
 				| BR_V )		/* valid */
-#define CFG_OR1_PRELIM		( 0xFFFF8000		/* length 32K */ \
+#define CFG_NAND_OR_PRELIM	( 0xFFFF8000		/* length 32K */ \
 				| OR_FCM_CSCT \
 				| OR_FCM_CST \
 				| OR_FCM_CHT \
@@ -240,9 +256,25 @@
 				| OR_FCM_TRLX \
 				| OR_FCM_EHTR )
 				/* 0xFFFF8396 */
+
+#ifdef CONFIG_NAND_U_BOOT
+#define CFG_BR0_PRELIM CFG_NAND_BR_PRELIM
+#define CFG_OR0_PRELIM CFG_NAND_OR_PRELIM
+#define CFG_BR1_PRELIM CFG_NOR_BR_PRELIM
+#define CFG_OR1_PRELIM CFG_NOR_OR_PRELIM
+#else
+#define CFG_BR0_PRELIM CFG_NOR_BR_PRELIM
+#define CFG_OR0_PRELIM CFG_NOR_OR_PRELIM
+#define CFG_BR1_PRELIM CFG_NAND_BR_PRELIM
+#define CFG_OR1_PRELIM CFG_NAND_OR_PRELIM
+#endif
+
 #define CFG_LBLAWBAR1_PRELIM	CFG_NAND_BASE
 #define CFG_LBLAWAR1_PRELIM	0x8000000E	/* 32KB  */
 
+#define CFG_NAND_LBLAWBAR_PRELIM CFG_LBLAWBAR1_PRELIM
+#define CFG_NAND_LBLAWAR_PRELIM CFG_LBLAWAR1_PRELIM
+
 /* local bus read write buffer mapping */
 #define CFG_BR3_PRELIM		0xFA000801	/* map at 0xFA000000 */
 #define CFG_OR3_PRELIM		0xFFFF8FF7	/* 32kB */
@@ -274,7 +306,6 @@
 #define CFG_NS16550
 #define CFG_NS16550_SERIAL
 #define CFG_NS16550_REG_SIZE	1
-#define CFG_NS16550_CLK		get_bus_freq(0)
 
 #define CFG_BAUDRATE_TABLE	\
 	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 115200}
@@ -353,7 +384,15 @@
 /*
  * Environment
  */
-#ifndef CFG_RAMBOOT
+#if defined(CONFIG_NAND_U_BOOT)
+	#define CFG_ENV_IS_IN_NAND      1
+	#define CFG_ENV_OFFSET          (512 * 1024)
+	#define CFG_ENV_SECT_SIZE       CFG_NAND_BLOCK_SIZE
+	#define CFG_ENV_SIZE            CFG_ENV_SECT_SIZE
+	#define CFG_ENV_SIZE_REDUND     CFG_ENV_SIZE
+	#define CFG_ENV_RANGE           (CFG_ENV_SECT_SIZE * 4)
+	#define CFG_ENV_OFFSET_REDUND   (CFG_ENV_OFFSET + CFG_ENV_RANGE)
+#elif !defined(CFG_RAMBOOT)
 	#define CFG_ENV_IS_IN_FLASH	1
 	#define CFG_ENV_ADDR		(CFG_MONITOR_BASE + CFG_MONITOR_LEN)
 	#define CFG_ENV_SECT_SIZE	0x10000	/* 64K(one sector) for env */
@@ -390,7 +429,7 @@
 #define CONFIG_CMD_DATE
 #define CONFIG_CMD_PCI
 
-#if defined(CFG_RAMBOOT)
+#if defined(CFG_RAMBOOT) && !defined(CONFIG_NAND_U_BOOT)
     #undef CONFIG_CMD_ENV
     #undef CONFIG_CMD_LOADS
 #endif
@@ -432,6 +471,8 @@
 	HRCWL_CSB_TO_CLKIN_2X1 |\
 	HRCWL_CORE_TO_CSB_2X1)
 
+#define CFG_NS16550_CLK (CONFIG_83XX_CLKIN * 2)
+
 #elif defined(CFG_33MHZ)
 
 /* 33MHz IN, 165MHz CSB, 330 DDR, 330 CORE */
@@ -444,22 +485,31 @@
 	HRCWL_CSB_TO_CLKIN_5X1 |\
 	HRCWL_CORE_TO_CSB_2X1)
 
+#define CFG_NS16550_CLK (CONFIG_83XX_CLKIN * 5)
+
 #endif
 
-/* 0xa0606c00 */
-#define CFG_HRCW_HIGH (\
+#define CFG_HRCW_HIGH_BASE (\
 	HRCWH_PCI_HOST |\
 	HRCWH_PCI1_ARBITER_ENABLE |\
 	HRCWH_CORE_ENABLE |\
-	HRCWH_FROM_0X00000100 |\
 	HRCWH_BOOTSEQ_DISABLE |\
 	HRCWH_SW_WATCHDOG_DISABLE |\
-	HRCWH_ROM_LOC_LOCAL_16BIT |\
-	HRCWH_RL_EXT_LEGACY |\
 	HRCWH_TSEC1M_IN_RGMII |\
 	HRCWH_TSEC2M_IN_RGMII |\
-	HRCWH_BIG_ENDIAN |\
-	HRCWH_LALE_NORMAL)
+	HRCWH_BIG_ENDIAN)
+
+#ifdef CONFIG_NAND_SPL
+#define CFG_HRCW_HIGH (CFG_HRCW_HIGH_BASE |\
+                       HRCWH_FROM_0XFFF00100 |\
+                       HRCWH_ROM_LOC_NAND_SP_8BIT |\
+                       HRCWH_RL_EXT_NAND)
+#else
+#define CFG_HRCW_HIGH (CFG_HRCW_HIGH_BASE |\
+                       HRCWH_FROM_0X00000100 |\
+                       HRCWH_ROM_LOC_LOCAL_16BIT |\
+                       HRCWH_RL_EXT_LEGACY)
+#endif
 
 /* System IO Config */
 #define CFG_SICRH	(SICRH_TSOBI1 | SICRH_TSOBI2)	/* RGMII */
diff --git a/include/mpc83xx.h b/include/mpc83xx.h
index 897ecd6..70a4de7 100644
--- a/include/mpc83xx.h
+++ b/include/mpc83xx.h
@@ -30,7 +30,9 @@
 
 /* IMMRBAR - Internal Memory Register Base Address
  */
+#ifndef CONFIG_DEFAULT_IMMR
 #define CONFIG_DEFAULT_IMMR		0xFF400000	/* Default IMMR base address */
+#endif
 #define IMMRBAR				0x0000		/* Register offset to immr */
 #define IMMRBAR_BASE_ADDR		0xFFF00000	/* Base address mask */
 #define IMMRBAR_RES			~(IMMRBAR_BASE_ADDR)
diff --git a/include/nand.h b/include/nand.h
index d5af432..764e9f9 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -126,5 +126,7 @@ int nand_get_lock_status(nand_info_t *meminfo, ulong offset);
 void board_nand_select_device(struct nand_chip *nand, int chip);
 #endif
 
+__attribute__((noreturn)) void nand_boot(void);
+
 #endif /* !CFG_NAND_LEGACY */
 #endif
diff --git a/lib_ppc/time.c b/lib_ppc/time.c
index 2649d5f..f093a57 100644
--- a/lib_ppc/time.c
+++ b/lib_ppc/time.c
@@ -67,7 +67,7 @@ void udelay(unsigned long usec)
 }
 
 /* ------------------------------------------------------------------------- */
-
+#ifndef CONFIG_NAND_SPL
 unsigned long ticks2usec(unsigned long ticks)
 {
 	ulong tbclk = get_tbclk();
@@ -83,7 +83,7 @@ unsigned long ticks2usec(unsigned long ticks)
 
 	return ((ulong)ticks);
 }
-
+#endif
 /* ------------------------------------------------------------------------- */
 
 int init_timebase (void)
diff --git a/nand_spl/board/freescale/mpc8313erdb/Makefile b/nand_spl/board/freescale/mpc8313erdb/Makefile
new file mode 100644
index 0000000..3da1b1f
--- /dev/null
+++ b/nand_spl/board/freescale/mpc8313erdb/Makefile
@@ -0,0 +1,101 @@
+#
+# (C) Copyright 2007
+# Stefan Roese, DENX Software Engineering, sr at denx.de.
+# (C) Copyright 2008 Freescale Semiconductor
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+NAND_SPL := y
+TEXT_BASE := 0xfff00000
+PAD_TO := 0xfff04000
+
+include $(TOPDIR)/config.mk
+
+LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
+LDFLAGS	= -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
+AFLAGS	+= -DCONFIG_NAND_SPL
+CFLAGS	+= -DCONFIG_NAND_SPL
+
+SOBJS	= start.o ticks.o
+COBJS	= nand_boot_fsl_elbc.o $(BOARD).o sdram.o ns16550.o nand_init.o time.o
+
+SRCS	:= $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+__OBJS	:= $(SOBJS) $(COBJS)
+LNDIR	:= $(OBJTREE)/nand_spl/board/$(BOARDDIR)
+
+nandobj	:= $(OBJTREE)/nand_spl/
+
+ALL	= $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
+
+all:	$(obj).depend $(ALL)
+
+$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl
+	$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@
+
+$(nandobj)u-boot-spl.bin:	$(nandobj)u-boot-spl
+	$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
+$(nandobj)u-boot-spl:	$(OBJS)
+	cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
+		-Map $(nandobj)u-boot-spl.map \
+		-o $(nandobj)u-boot-spl
+
+# create symbolic links for common files
+
+$(obj)start.S:
+	ln -sf $(SRCTREE)/cpu/mpc83xx/start.S $(obj)start.S
+
+$(obj)nand_boot_fsl_elbc.c:
+	ln -sf $(SRCTREE)/nand_spl/nand_boot_fsl_elbc.c \
+	       $(obj)nand_boot_fsl_elbc.c
+
+$(obj)sdram.c:
+	ln -sf $(SRCTREE)/board/$(BOARDDIR)/sdram.c $(obj)sdram.c
+
+$(obj)$(BOARD).c:
+	ln -sf $(SRCTREE)/board/$(BOARDDIR)/$(BOARD).c $(obj)$(BOARD).c
+
+$(obj)ns16550.c:
+	ln -sf $(SRCTREE)/drivers/serial/ns16550.c $(obj)ns16550.c
+
+$(obj)nand_init.c:
+	ln -sf $(SRCTREE)/cpu/mpc83xx/nand_init.c $(obj)nand_init.c
+
+$(obj)time.c:
+	ln -sf $(SRCTREE)/lib_ppc/time.c $(obj)time.c
+
+$(obj)ticks.S:
+	ln -sf $(SRCTREE)/lib_ppc/ticks.S $(obj)ticks.S
+
+#########################################################################
+
+$(obj)%.o:	$(obj)%.S
+	$(CC) $(AFLAGS) -c -o $@ $<
+
+$(obj)%.o:	$(obj)%.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/nand_spl/board/freescale/mpc8313erdb/u-boot.lds b/nand_spl/board/freescale/mpc8313erdb/u-boot.lds
new file mode 100644
index 0000000..40c4145
--- /dev/null
+++ b/nand_spl/board/freescale/mpc8313erdb/u-boot.lds
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+	. = 0xfff00000;
+	.text : {
+		*(.text*)
+		. = ALIGN(16);
+		*(.rodata*)
+		*(.eh_frame)
+	}
+
+	. = ALIGN(8);
+	.data : {
+		*(.data*)
+		*(.sdata*)
+		_GOT2_TABLE_ = .;
+		*(.got2)
+		__got2_entries = (. - _GOT2_TABLE_) >> 2;
+	}
+
+	. = ALIGN(8);
+	__bss_start = .;
+	.bss (NOLOAD) : { *(.*bss) }
+	_end = .;
+}
+ENTRY(_start)
+ASSERT(_end <= 0xfff01000, "NAND bootstrap too big");
diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c
index 5914d04..0f56ba5 100644
--- a/nand_spl/nand_boot.c
+++ b/nand_spl/nand_boot.c
@@ -235,7 +235,7 @@ void nand_boot(void)
 	struct nand_chip nand_chip;
 	nand_info_t nand_info;
 	int ret;
-	void (*uboot)(void);
+	__attribute__((noreturn)) void (*uboot)(void);
 
 	/*
 	 * Init board specific nand support
@@ -254,6 +254,6 @@ void nand_boot(void)
 	/*
 	 * Jump to U-Boot image
 	 */
-	uboot = (void (*)(void))CFG_NAND_U_BOOT_START;
+	uboot = (void *)CFG_NAND_U_BOOT_START;
 	(*uboot)();
 }
diff --git a/nand_spl/nand_boot_fsl_elbc.c b/nand_spl/nand_boot_fsl_elbc.c
new file mode 100644
index 0000000..0d2378e
--- /dev/null
+++ b/nand_spl/nand_boot_fsl_elbc.c
@@ -0,0 +1,150 @@
+/*
+ * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine
+ *
+ * (C) Copyright 2006-2008
+ * Stefan Roese, DENX Software Engineering, sr at denx.de.
+ *
+ * Copyright (c) 2008 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood at freescale.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_83xx.h>
+#include <asm/fsl_lbc.h>
+#include <linux/mtd/nand.h>
+
+#define WINDOW_SIZE 8192
+
+static void nand_wait(void)
+{
+	lbus83xx_t *regs = (lbus83xx_t *)(CFG_IMMR + 0x5000);
+
+	for (;;) {
+		uint32_t status = in_be32(&regs->ltesr);
+
+		if (status == 1)
+			return;
+
+		if (status & 1) {
+			puts("read failed (ltesr)\n");
+			for (;;);
+		}
+	}
+}
+
+static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
+{
+	lbus83xx_t *regs = (lbus83xx_t *)(CFG_IMMR + 0x5000);
+	uchar *buf = (uchar *)CFG_NAND_BASE;
+	int large = in_be32(&regs->bank[0].or) & OR_FCM_PGS;
+	int block_shift = large ? 17 : 14;
+	int block_size = 1 << block_shift;
+	int page_size = large ? 2048 : 512;
+	int bad_marker = large ? page_size + 0 : page_size + 5;
+	int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2;
+	int pos = 0;
+
+	if (offs & (block_size - 1)) {
+		puts("bad offset\n");
+		for (;;);
+	}
+
+	if (large) {
+		fmr |= FMR_ECCM;
+		out_be32(&regs->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
+		                     (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+		out_be32(&regs->fir,
+		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
+		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
+		         (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+		         (FIR_OP_RBW << FIR_OP4_SHIFT));
+	} else {
+		out_be32(&regs->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
+		out_be32(&regs->fir,
+		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
+		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
+		         (FIR_OP_RBW << FIR_OP3_SHIFT));
+	}
+
+	out_be32(&regs->fbcr, 0);
+	clrsetbits_be32(&regs->bank[0].br, BR_DECC, BR_DECC_CHK_GEN);
+
+	while (pos < uboot_size) {
+		int i = 0;
+		out_be32(&regs->fbar, offs >> block_shift);
+
+		do {
+			int j;
+			unsigned int page_offs = (offs & (block_size - 1)) << 1;
+
+			out_be32(&regs->ltesr, ~0);
+			out_be32(&regs->lteatr, 0);
+			out_be32(&regs->fpar, page_offs);
+			out_be32(&regs->fmr, fmr);
+			out_be32(&regs->lsor, 0);
+			nand_wait();
+
+			page_offs %= WINDOW_SIZE;
+
+			/*
+			 * If either of the first two pages are marked bad,
+			 * continue to the next block.
+			 */
+			if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) {
+				puts("skipping\n");
+				offs = (offs + block_size) & ~(block_size - 1);
+				pos &= ~(block_size - 1);
+				break;
+			}
+
+			for (j = 0; j < page_size; j++)
+				dst[pos + j] = buf[page_offs + j];
+
+			pos += page_size;
+			offs += page_size;
+		} while (offs & (block_size - 1));
+	}
+}
+
+/*
+ * The main entry for NAND booting. It's necessary that SDRAM is already
+ * configured and available since this code loads the main U-Boot image
+ * from NAND into SDRAM and starts it from there.
+ */
+void nand_boot(void)
+{
+	__attribute__((noreturn)) void (*uboot)(void);
+
+	udelay(1000000);
+
+	/*
+	 * Load U-Boot image from NAND into RAM
+	 */
+	nand_load(CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE,
+	          (uchar *)CFG_NAND_U_BOOT_DST);
+
+	/*
+	 * Jump to U-Boot image
+	 */
+	puts("transfering control\n");
+	uboot = (void *)CFG_NAND_U_BOOT_START;
+	uboot();
+}
-- 
1.5.6.rc1.6.gc53ad




More information about the U-Boot mailing list