diff mbox

[U-Boot,9/10] board/b4qds:Add support of 2 stage NAND boot-loader

Message ID 1396260323-2751-1-git-send-email-prabhakar@freescale.com
State Superseded
Delegated to: York Sun
Headers show

Commit Message

Prabhakar Kushwaha March 31, 2014, 10:05 a.m. UTC
Add support of 2 stage NAND boot loader using SPL framework.
here, PBL initialise the internal SRAM and copy SPL(160KB). This further
initialise DDR using SPD and environment and copy u-boot(768 KB) from NAND to DDR.
Finally SPL transer control to u-boot.

Initialise/create followings required for SPL framework
  - Add spl.c which defines board_init_f, board_init_r
  - update tlb and ddr accordingly

Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
---
 board/freescale/b4860qds/Makefile |    9 ++-
 board/freescale/b4860qds/ddr.c    |    5 +-
 board/freescale/b4860qds/spl.c    |  115 +++++++++++++++++++++++++++++++++++++
 board/freescale/b4860qds/tlb.c    |   10 ++++
 boards.cfg                        |    4 +-
 doc/README.b4860qds               |   35 +++++++++++
 include/configs/B4860QDS.h        |   64 ++++++++++++++++++---
 7 files changed, 230 insertions(+), 12 deletions(-)
 create mode 100644 board/freescale/b4860qds/spl.c

Comments

Scott Wood April 1, 2014, 10:12 p.m. UTC | #1
On Mon, 2014-03-31 at 15:35 +0530, Prabhakar Kushwaha wrote:
> +void board_init_f(ulong bootflag)
> +{
> +	u32 plat_ratio, sys_clk, uart_clk;
> +	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
> +
> +	/* Memcpy existing GD at CONFIG_SPL_GD_ADDR */
> +	memcpy((void *)CONFIG_SPL_GD_ADDR, (void *)gd, sizeof(gd_t));
> +
> +	/* Update GD pointer */
> +	gd = (gd_t *)(CONFIG_SPL_GD_ADDR);
> +	__asm__ __volatile__("" : : : "memory");

Explain why this barrier is needed.


> +#ifndef CONFIG_SPL_NAND_BOOT
> +	env_init();
> +#endif
> +
> +	/* relocate environment function pointers etc. */
> +#ifdef CONFIG_SPL_NAND_BOOT
> +	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
> +			    (uchar *)CONFIG_ENV_ADDR);
> +	gd->env_addr  = (ulong)(CONFIG_ENV_ADDR);
> +	gd->env_valid = 1;
> +#else
> +	env_relocate();
> +#endif

Move env_init() to be just before env_relocate(), rather than
duplicating the ifdef.

> +	i2c_init_all();
> +
> +	puts("\n\n");
> +
> +	gd->ram_size = initdram(0);

What is the 0?

> diff --git a/doc/README.b4860qds b/doc/README.b4860qds
> index 3da77d9..44b46da 100644
> --- a/doc/README.b4860qds
> +++ b/doc/README.b4860qds
> @@ -328,3 +328,38 @@ The below commands apply to both B4860QDS and B4420QDS.
>     On Linux the interfaces are renamed as:
>  	. eth2 -> fm1-gb2
>  	. eth3 -> fm1-gb3
> +
> +NAND boot with 2 Stage boot loader
> +----------------------------------
> +PBL initialise the internal SRAM and copy SPL(160KB) in SRAM.
> +SPL further initialise DDR using SPD and environment variables and copy
> +u-boot(768 KB) from flash to DDR.
> +Finally SPL transer control to u-boot for futher booting.
> +
> +SPL has following features:
> + - Executes within 256K
> + - No relocation required
> +
> + Run time view of SPL framework :-
> + -----------------------------------------------
> + Area        | Address                         |
> +-----------------------------------------------
> + Reserve     | 0xFFFC0000 (32KB)               |

s/Reserve/Reserved/

What is it reserved for/by?  Something external?  Or does U-Boot just
not use that area currently?  In that case just say "Unused".

> +NAND Flash memory Map on B4860 and B4420QDS
> +------------------------------------------
> + Start		 End		Definition			Size
> +0x000000	0x0FFFFF	u-boot                          1MB
> +0x140000	0x15FFFF	u-boot env                      128KB
> +0x160000	0x17FFFF	FMAN Ucode                      128KB

What goes at 0x100000?

What if 0x140000 or 0x160000 is a bad block?

-Scott
Prabhakar Kushwaha April 2, 2014, 3:59 a.m. UTC | #2
On 4/2/2014 3:42 AM, Scott Wood wrote:
> On Mon, 2014-03-31 at 15:35 +0530, Prabhakar Kushwaha wrote:
>> +void board_init_f(ulong bootflag)
>> +{
>> +	u32 plat_ratio, sys_clk, uart_clk;
>> +	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
>> +
>> +	/* Memcpy existing GD at CONFIG_SPL_GD_ADDR */
>> +	memcpy((void *)CONFIG_SPL_GD_ADDR, (void *)gd, sizeof(gd_t));
>> +
>> +	/* Update GD pointer */
>> +	gd = (gd_t *)(CONFIG_SPL_GD_ADDR);
>> +	__asm__ __volatile__("" : : : "memory");
> Explain why this barrier is needed.
>

I followed similar to what is present in arch/powerpc/lib/board.c.
There is is mentioned like
     /* compiler optimization barrier needed for GCC >= 3.4 */
     __asm__ __volatile__("":::"memory");

may i mention this comment here also.


>> +#ifndef CONFIG_SPL_NAND_BOOT
>> +	env_init();
>> +#endif
>> +
>> +	/* relocate environment function pointers etc. */
>> +#ifdef CONFIG_SPL_NAND_BOOT
>> +	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
>> +			    (uchar *)CONFIG_ENV_ADDR);
>> +	gd->env_addr  = (ulong)(CONFIG_ENV_ADDR);
>> +	gd->env_valid = 1;
>> +#else
>> +	env_relocate();
>> +#endif
> Move env_init() to be just before env_relocate(), rather than
> duplicating the ifdef.

sure, I will do it.

>> +	i2c_init_all();
>> +
>> +	puts("\n\n");
>> +
>> +	gd->ram_size = initdram(0);
> What is the 0?

here  0 is board type.

in arch/powerpc/lib/board.c , we pass it as 0 "dummy arg".
Same I am following here

>> diff --git a/doc/README.b4860qds b/doc/README.b4860qds
>> index 3da77d9..44b46da 100644
>> --- a/doc/README.b4860qds
>> +++ b/doc/README.b4860qds
>> @@ -328,3 +328,38 @@ The below commands apply to both B4860QDS and B4420QDS.
>>      On Linux the interfaces are renamed as:
>>   	. eth2 -> fm1-gb2
>>   	. eth3 -> fm1-gb3
>> +
>> +NAND boot with 2 Stage boot loader
>> +----------------------------------
>> +PBL initialise the internal SRAM and copy SPL(160KB) in SRAM.
>> +SPL further initialise DDR using SPD and environment variables and copy
>> +u-boot(768 KB) from flash to DDR.
>> +Finally SPL transer control to u-boot for futher booting.
>> +
>> +SPL has following features:
>> + - Executes within 256K
>> + - No relocation required
>> +
>> + Run time view of SPL framework :-
>> + -----------------------------------------------
>> + Area        | Address                         |
>> +-----------------------------------------------
>> + Reserve     | 0xFFFC0000 (32KB)               |
> s/Reserve/Reserved/
>
> What is it reserved for/by?  Something external?  Or does U-Boot just
> not use that area currently?  In that case just say "Unused".
Secure boot requires some memory in SRAM in order to put  some headers etc.
May be I mention in README also

>> +NAND Flash memory Map on B4860 and B4420QDS
>> +------------------------------------------
>> + Start		 End		Definition			Size
>> +0x000000	0x0FFFFF	u-boot                          1MB
>> +0x140000	0x15FFFF	u-boot env                      128KB
>> +0x160000	0x17FFFF	FMAN Ucode                      128KB
> What goes at 0x100000?

I think, ENV can start from here.

> What if 0x140000 or 0x160000 is a bad block?
>
>
it can be true for any region. I believe it will be taken care by MTD 
layer to read next good block.

are you suggesting to have a hole of 1 block between every regions.

Regards,
Prabhakar
Scott Wood April 4, 2014, 9:47 p.m. UTC | #3
On Wed, 2014-04-02 at 09:29 +0530, Prabhakar Kushwaha wrote:
> On 4/2/2014 3:42 AM, Scott Wood wrote:
> > On Mon, 2014-03-31 at 15:35 +0530, Prabhakar Kushwaha wrote:
> >> +void board_init_f(ulong bootflag)
> >> +{
> >> +	u32 plat_ratio, sys_clk, uart_clk;
> >> +	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
> >> +
> >> +	/* Memcpy existing GD at CONFIG_SPL_GD_ADDR */
> >> +	memcpy((void *)CONFIG_SPL_GD_ADDR, (void *)gd, sizeof(gd_t));
> >> +
> >> +	/* Update GD pointer */
> >> +	gd = (gd_t *)(CONFIG_SPL_GD_ADDR);
> >> +	__asm__ __volatile__("" : : : "memory");
> > Explain why this barrier is needed.
> >
> 
> I followed similar to what is present in arch/powerpc/lib/board.c.
> There is is mentioned like
>      /* compiler optimization barrier needed for GCC >= 3.4 */
>      __asm__ __volatile__("":::"memory");
> 
> may i mention this comment here also.

Yes, at least retain the comment when you copy the code.

> >> +	i2c_init_all();
> >> +
> >> +	puts("\n\n");
> >> +
> >> +	gd->ram_size = initdram(0);
> > What is the 0?
> 
> here  0 is board type.
> 
> in arch/powerpc/lib/board.c , we pass it as 0 "dummy arg".
> Same I am following here

Right, that comment was more for York -- why do we have this dummy
argument?

> >> + Run time view of SPL framework :-
> >> + -----------------------------------------------
> >> + Area        | Address                         |
> >> +-----------------------------------------------
> >> + Reserve     | 0xFFFC0000 (32KB)               |
> > s/Reserve/Reserved/
> >
> > What is it reserved for/by?  Something external?  Or does U-Boot just
> > not use that area currently?  In that case just say "Unused".
> Secure boot requires some memory in SRAM in order to put  some headers etc.
> May be I mention in README also

Secure boot is no longer running at this point, so why does it care?

Or do you mean that code in U-Boot uses this for validating the next
image (in which case, it's not reserved, but rather used for that
purpose)?

> >> +NAND Flash memory Map on B4860 and B4420QDS
> >> +------------------------------------------
> >> + Start		 End		Definition			Size
> >> +0x000000	0x0FFFFF	u-boot                          1MB
> >> +0x140000	0x15FFFF	u-boot env                      128KB
> >> +0x160000	0x17FFFF	FMAN Ucode                      128KB
> > What goes at 0x100000?
> 
> I think, ENV can start from here.
> 
> > What if 0x140000 or 0x160000 is a bad block?
> >
> >
> it can be true for any region. I believe it will be taken care by MTD 
> layer to read next good block.

No, it won't.  Imagine if it did, and 0x140000 were bad, and it used
0x160000 instead.  Then where would FMAN Ucode go?

> are you suggesting to have a hole of 1 block between every regions.

There are a variety of options for dealing with this for the
environment.  One of them is leaving a range of blocks (more than two --
consecutive blocks can be bad) within which block skipping can be done.
This can be fairly wasteful, especially if you'd extend it to other
things like microcode.

Another way is to put the environment in UBI, but that means you can't
load the environment during SPL or before relocation.

My suggestion would be to put non-environment things in UBI.  For the
environment, either use CONFIG_ENV_RANGE, or append the environment
(block-aligned) to the U-Boot image so it can participate in its bad
block skipping without having to reserve another large chunk.

Also consider having a redundant environment, IIRC this will need
additional work to function with any of the bad block handling
approaches.

-Scott
diff mbox

Patch

diff --git a/board/freescale/b4860qds/Makefile b/board/freescale/b4860qds/Makefile
index e5cc054..0acd2a9 100644
--- a/board/freescale/b4860qds/Makefile
+++ b/board/freescale/b4860qds/Makefile
@@ -4,9 +4,14 @@ 
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+ifdef CONFIG_SPL_BUILD
+obj-y += spl.o
+else
 obj-y	+= b4860qds.o
-obj-y	+= ddr.o
 obj-$(CONFIG_B4860QDS)+= eth_b4860qds.o
-obj-$(CONFIG_PCI)	+= pci.o
+obj-$(CONFIG_PCI)      += pci.o
+endif
+
+obj-y	+= ddr.o
 obj-y	+= law.o
 obj-y	+= tlb.o
diff --git a/board/freescale/b4860qds/ddr.c b/board/freescale/b4860qds/ddr.c
index 187c3b3..2c17156 100644
--- a/board/freescale/b4860qds/ddr.c
+++ b/board/freescale/b4860qds/ddr.c
@@ -179,6 +179,7 @@  phys_size_t initdram(int board_type)
 {
 	phys_size_t dram_size;
 
+#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
 
 	dram_size = fsl_ddr_sdram();
@@ -186,7 +187,9 @@  phys_size_t initdram(int board_type)
 	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
 	dram_size *= 0x100000;
 
-	puts("    DDR: ");
+#else
+	dram_size =  fsl_ddr_sdram_size();
+#endif
 	return dram_size;
 }
 
diff --git a/board/freescale/b4860qds/spl.c b/board/freescale/b4860qds/spl.c
new file mode 100644
index 0000000..d56cd30
--- /dev/null
+++ b/board/freescale/b4860qds/spl.c
@@ -0,0 +1,115 @@ 
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/spl.h>
+#include <malloc.h>
+#include <ns16550.h>
+#include <nand.h>
+#include <i2c.h>
+#include "../common/qixis.h"
+#include "b4860qds_qixis.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+phys_size_t get_effective_memsize(void)
+{
+	return CONFIG_SYS_L3_SIZE;
+}
+
+unsigned long get_board_sys_clk(void)
+{
+	u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
+
+	switch ((sysclk_conf & 0x0C) >> 2) {
+	case QIXIS_CLK_100:
+		return 100000000;
+	case QIXIS_CLK_125:
+		return 125000000;
+	case QIXIS_CLK_133:
+		return 133333333;
+	}
+	return 66666666;
+}
+
+unsigned long get_board_ddr_clk(void)
+{
+	u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
+
+	switch (ddrclk_conf & 0x03) {
+	case QIXIS_CLK_100:
+		return 100000000;
+	case QIXIS_CLK_125:
+		return 125000000;
+	case QIXIS_CLK_133:
+		return 133333333;
+	}
+	return 66666666;
+}
+
+void board_init_f(ulong bootflag)
+{
+	u32 plat_ratio, sys_clk, uart_clk;
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* Memcpy existing GD at CONFIG_SPL_GD_ADDR */
+	memcpy((void *)CONFIG_SPL_GD_ADDR, (void *)gd, sizeof(gd_t));
+
+	/* Update GD pointer */
+	gd = (gd_t *)(CONFIG_SPL_GD_ADDR);
+	__asm__ __volatile__("" : : : "memory");
+
+	console_init_f();
+
+	/* initialize selected port with appropriate baud rate */
+	sys_clk = get_board_sys_clk();
+	plat_ratio = (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f;
+	uart_clk = sys_clk * plat_ratio / 2;
+
+	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+		     uart_clk / 16 / CONFIG_BAUDRATE);
+
+	relocate_code(CONFIG_SPL_RELOC_STACK, (gd_t *)CONFIG_SPL_GD_ADDR, 0x0);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+	bd_t *bd;
+
+	bd = (bd_t *)(gd + sizeof(gd_t));
+	memset(bd, 0, sizeof(bd_t));
+	gd->bd = bd;
+	bd->bi_memstart = CONFIG_SYS_INIT_L3_ADDR;
+	bd->bi_memsize = CONFIG_SYS_L3_SIZE;
+
+	probecpu();
+	get_clocks();
+	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
+			CONFIG_SPL_RELOC_MALLOC_SIZE);
+
+#ifndef CONFIG_SPL_NAND_BOOT
+	env_init();
+#endif
+
+	/* relocate environment function pointers etc. */
+#ifdef CONFIG_SPL_NAND_BOOT
+	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+			    (uchar *)CONFIG_ENV_ADDR);
+	gd->env_addr  = (ulong)(CONFIG_ENV_ADDR);
+	gd->env_valid = 1;
+#else
+	env_relocate();
+#endif
+
+	i2c_init_all();
+
+	puts("\n\n");
+
+	gd->ram_size = initdram(0);
+
+#ifdef CONFIG_SPL_NAND_BOOT
+	nand_boot();
+#endif
+}
diff --git a/board/freescale/b4860qds/tlb.c b/board/freescale/b4860qds/tlb.c
index 00798a1..7b55b86 100644
--- a/board/freescale/b4860qds/tlb.c
+++ b/board/freescale/b4860qds/tlb.c
@@ -62,6 +62,7 @@  struct fsl_e_tlb_entry tlb_table[] = {
 		      MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
 		      0, 2, BOOKE_PAGESZ_256M, 1),
 
+#ifndef CONFIG_SPL_BUILD
 	/* *I*G* - PCI */
 	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -96,6 +97,7 @@  struct fsl_e_tlb_entry tlb_table[] = {
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 9, BOOKE_PAGESZ_16M, 1),
 #endif
+#endif
 #ifdef CONFIG_SYS_DCSRBAR_PHYS
 	SET_TLB_ENTRY(1, CONFIG_SYS_DCSRBAR, CONFIG_SYS_DCSRBAR_PHYS,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -118,6 +120,7 @@  struct fsl_e_tlb_entry tlb_table[] = {
 	 * entry 14 and 15 has been used hard coded, they will be disabled
 	 * in cpu_init_f, so we use entry 16 for SRIO2.
 	 */
+#ifndef CONFIG_SPL_BUILD
 #ifdef CONFIG_SYS_SRIO1_MEM_PHYS
 	/* *I*G* - SRIO1 */
 	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO1_MEM_VIRT, CONFIG_SYS_SRIO1_MEM_PHYS,
@@ -140,6 +143,13 @@  struct fsl_e_tlb_entry tlb_table[] = {
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
 		      0, 17, BOOKE_PAGESZ_1M, 1),
 #endif
+#endif
+
+#if defined(CONFIG_RAMBOOT_PBL) && !defined(CONFIG_SPL_BUILD)
+	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 17, BOOKE_PAGESZ_2G, 1)
+#endif
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/boards.cfg b/boards.cfg
index 5afca26..76f3aae 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -740,10 +740,10 @@  Active  powerpc     mpc85xx        -           -               sbc8548
 Active  powerpc     mpc85xx        -           -               socrates            socrates                             -                                                                                                                                 -
 Active  powerpc     mpc85xx        -           exmeritus       hww1u1a             HWW1U1A                              -                                                                                                                                 Kyle Moffett <Kyle.D.Moffett@boeing.com>
 Active  powerpc     mpc85xx        -           freescale       b4860qds            B4420QDS                             B4860QDS:PPC_B4420                                                                                                                -
-Active  powerpc     mpc85xx        -           freescale       b4860qds            B4420QDS_NAND                        B4860QDS:PPC_B4420,RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF40000                                                                      -
+Active  powerpc     mpc85xx        -           freescale       b4860qds            B4420QDS_NAND                        B4860QDS:PPC_B4420,RAMBOOT_PBL,RAMBOOT_SPLPBL,NAND                                                                      -
 Active  powerpc     mpc85xx        -           freescale       b4860qds            B4420QDS_SPIFLASH                    B4860QDS:PPC_B4420,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF40000                                                                  -
 Active  powerpc     mpc85xx        -           freescale       b4860qds            B4860QDS                             B4860QDS:PPC_B4860                                                                                                                -
-Active  powerpc     mpc85xx        -           freescale       b4860qds            B4860QDS_NAND                        B4860QDS:PPC_B4860,RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF40000                                                                      -
+Active  powerpc     mpc85xx        -           freescale       b4860qds            B4860QDS_NAND                        B4860QDS:PPC_B4860,RAMBOOT_PBL,RAMBOOT_SPLPBL,NAND
 Active  powerpc     mpc85xx        -           freescale       b4860qds            B4860QDS_SPIFLASH                    B4860QDS:PPC_B4860,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF40000                                                                  -
 Active  powerpc     mpc85xx        -           freescale       b4860qds            B4860QDS_SRIO_PCIE_BOOT              B4860QDS:PPC_B4860,SRIO_PCIE_BOOT_SLAVE,SYS_TEXT_BASE=0xFFF40000                                                                  -
 Active  powerpc     mpc85xx        -           freescale       bsc9131rdb          BSC9131RDB_NAND                      BSC9131RDB:BSC9131RDB,NAND                                                                                                        Poonam Aggrwal <poonam.aggrwal@freescale.com>
diff --git a/doc/README.b4860qds b/doc/README.b4860qds
index 3da77d9..44b46da 100644
--- a/doc/README.b4860qds
+++ b/doc/README.b4860qds
@@ -328,3 +328,38 @@  The below commands apply to both B4860QDS and B4420QDS.
    On Linux the interfaces are renamed as:
 	. eth2 -> fm1-gb2
 	. eth3 -> fm1-gb3
+
+NAND boot with 2 Stage boot loader
+----------------------------------
+PBL initialise the internal SRAM and copy SPL(160KB) in SRAM.
+SPL further initialise DDR using SPD and environment variables and copy
+u-boot(768 KB) from flash to DDR.
+Finally SPL transer control to u-boot for futher booting.
+
+SPL has following features:
+ - Executes within 256K
+ - No relocation required
+
+ Run time view of SPL framework :-
+ -----------------------------------------------
+ Area        | Address                         |
+-----------------------------------------------
+ Reserve     | 0xFFFC0000 (32KB)               |
+ -----------------------------------------------
+ GD, BD      | 0xFFFC8000 (4KB)                |
+ -----------------------------------------------
+ ENV         | 0xFFFC9000 (6KB)                |
+ -----------------------------------------------
+ HEAP        | 0xFFFCA800 (30KB)               |
+ -----------------------------------------------
+ STACK       | 0xFFFD8000 (20KB)               |
+ -----------------------------------------------
+ U-boot SPL  | 0xFFFD8000 (160KB)              |
+ -----------------------------------------------
+
+NAND Flash memory Map on B4860 and B4420QDS
+------------------------------------------
+ Start		 End		Definition			Size
+0x000000	0x0FFFFF	u-boot                          1MB
+0x140000	0x15FFFF	u-boot env                      128KB
+0x160000	0x17FFFF	FMAN Ucode                      128KB
diff --git a/include/configs/B4860QDS.h b/include/configs/B4860QDS.h
index 8fcd1de..4df28a2 100644
--- a/include/configs/B4860QDS.h
+++ b/include/configs/B4860QDS.h
@@ -14,10 +14,43 @@ 
 #define CONFIG_PHYS_64BIT
 
 #ifdef CONFIG_RAMBOOT_PBL
+#define CONFIG_SYS_FSL_PBL_PBI	$(SRCTREE)/board/freescale/b4860qds/b4_pbi.cfg
+#define CONFIG_SYS_FSL_PBL_RCW	$(SRCTREE)/board/freescale/b4860qds/b4_rcw.cfg
+#ifndef CONFIG_NAND
 #define CONFIG_RAMBOOT_TEXT_BASE	CONFIG_SYS_TEXT_BASE
 #define CONFIG_RESET_VECTOR_ADDRESS	0xfffffffc
-#define CONFIG_SYS_FSL_PBL_PBI	board/freescale/b4860qds/b4_pbi.cfg
-#define CONFIG_SYS_FSL_PBL_RCW	board/freescale/b4860qds/b4_rcw.cfg
+#else
+#define CONFIG_SPL
+#define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
+#define CONFIG_SPL_ENV_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_FLUSH_IMAGE
+#define CONFIG_SPL_TARGET		"u-boot-with-spl.bin"
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+#define CONFIG_FSL_LAW                 /* Use common FSL init code */
+#define CONFIG_SYS_TEXT_BASE		0x00201000
+#define CONFIG_SPL_TEXT_BASE		0xFFFD8000
+#define CONFIG_SPL_PAD_TO		0x40000
+#define CONFIG_SPL_MAX_SIZE		0x28000
+#define RESET_VECTOR_OFFSET		0x27FFC
+#define BOOT_PAGE_OFFSET		0x27000
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	(768 << 10)
+#define CONFIG_SYS_NAND_U_BOOT_DST	0x00200000
+#define CONFIG_SYS_NAND_U_BOOT_START	0x00200000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	(256 << 10)
+#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
+#define CONFIG_SPL_NAND_BOOT
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SPL_SKIP_RELOCATE
+#define CONFIG_SPL_COMMON_INIT_DDR
+#define CONFIG_SYS_CCSR_DO_NOT_RELOCATE
+#define CONFIG_SYS_NO_FLASH
+#endif
+#endif
 #endif
 
 #ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
@@ -113,8 +146,8 @@ 
 #elif defined(CONFIG_NAND)
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #define CONFIG_ENV_IS_IN_NAND
-#define CONFIG_ENV_SIZE			CONFIG_SYS_NAND_BLOCK_SIZE
-#define CONFIG_ENV_OFFSET		(7 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#define CONFIG_ENV_SIZE			0x2000
+#define CONFIG_ENV_OFFSET		(10 * CONFIG_SYS_NAND_BLOCK_SIZE)
 #elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
 #define CONFIG_ENV_IS_IN_REMOTE
 #define CONFIG_ENV_ADDR		0xffe20000
@@ -164,7 +197,16 @@  unsigned long get_board_ddr_clk(void);
 /*
  *  Config the L3 Cache as L3 SRAM
  */
-#define CONFIG_SYS_INIT_L3_ADDR		CONFIG_RAMBOOT_TEXT_BASE
+#define CONFIG_SYS_INIT_L3_ADDR		0xFFFC0000
+#define CONFIG_SYS_L3_SIZE		256 << 10
+#define CONFIG_SPL_GD_ADDR		(CONFIG_SYS_INIT_L3_ADDR + 32 * 1024)
+#ifdef CONFIG_NAND
+#define CONFIG_ENV_ADDR			(CONFIG_SPL_GD_ADDR + 4 * 1024)
+#endif
+#define CONFIG_SPL_RELOC_MALLOC_ADDR	(CONFIG_SPL_GD_ADDR + 10 * 1024)
+#define CONFIG_SPL_RELOC_MALLOC_SIZE	(34 << 10)
+#define CONFIG_SPL_RELOC_STACK		(CONFIG_SPL_GD_ADDR + 64 * 1024)
+#define CONFIG_SPL_RELOC_STACK_SIZE	(20 << 10)
 
 #ifdef CONFIG_PHYS_64BIT
 #define CONFIG_SYS_DCSRBAR		0xf0000000
@@ -193,7 +235,9 @@  unsigned long get_board_ddr_clk(void);
 #define CONFIG_DDR_SPD
 #define CONFIG_SYS_DDR_RAW_TIMING
 #define CONFIG_SYS_FSL_DDR3
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_FSL_DDR_INTERACTIVE
+#endif
 
 #define CONFIG_SYS_SPD_BUS_NUM	0
 #define SPD_EEPROM_ADDRESS1	0x51
@@ -381,7 +425,11 @@  unsigned long get_board_ddr_clk(void);
 #define CONFIG_SYS_CS1_FTIM2		CONFIG_SYS_NOR_FTIM2
 #define CONFIG_SYS_CS1_FTIM3		CONFIG_SYS_NOR_FTIM3
 
-#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MONITOR_BASE	CONFIG_SPL_TEXT_BASE
+#else
+#define CONFIG_SYS_MONITOR_BASE	CONFIG_SYS_TEXT_BASE	/* start of monitor */
+#endif
 
 #if defined(CONFIG_RAMBOOT_PBL)
 #define CONFIG_SYS_RAMBOOT
@@ -435,7 +483,9 @@  unsigned long get_board_ddr_clk(void);
 #define CONFIG_SYS_NS16550_COM3	(CONFIG_SYS_CCSRBAR+0x11D500)
 #define CONFIG_SYS_NS16550_COM4	(CONFIG_SYS_CCSRBAR+0x11D600)
 #define CONFIG_SERIAL_MULTI		/* Enable both serial ports */
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV	/* determine from environment */
+#endif
 
 
 /* Use the HUSH parser */
@@ -607,7 +657,7 @@  unsigned long get_board_ddr_clk(void);
 #define CONFIG_SYS_QE_FMAN_FW_ADDR	(512 * 1130)
 #elif defined(CONFIG_NAND)
 #define CONFIG_SYS_QE_FMAN_FW_IN_NAND
-#define CONFIG_SYS_QE_FMAN_FW_ADDR	(8 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#define CONFIG_SYS_QE_FMAN_FW_ADDR	(11 * CONFIG_SYS_NAND_BLOCK_SIZE)
 #elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
 /*
  * Slave has no ucode locally, it can fetch this from remote. When implementing