[U-Boot] [PATCH] powerpc/p1022ds: nand: introduce the TPL based on the SPL

ying.zhang at freescale.com ying.zhang at freescale.com
Sun Jun 9 07:54:43 CEST 2013


From: Ying Zhang <b40530 at freescale.com>

Due to the nand SPL on the board P1022DS has a size limit, it can not be
more than 4K. So, the SPL cannot initialize the DDR with the SPD code.
This patch introduces TPL to enable a loader stub that runs in the L2 SRAM,
after being loaded by the code from the SPL. It initializes the DDR with
the SPD.

The TPL's size is sizeable, the maximum size must not exceed the size of L2
SRAM. It initializes the DDR through SPD code, and copys final uboot image
to DDR. So there are three stage uboot images:
	* spl_boot, 4KB size, pad to 128K byte.
	* tpl_boot, 88K size, pad to 128K size. The env variables are
	copied to L2 SRAM, so that ddr SPD code can get the interleaving
	mode setting in env. It loads final uboot image from offset 256KB.
	* final uboot image, size is variable depends on the functions
        enabled.

This patch is on top of the patch:
powerpc/p1022ds: boot from SD Card with SPL

Signed-off-by: Ying Zhang <b40530 at freescale.com>
---
 Makefile                                           |   25 +++-
 README                                             |   55 ++++++-
 arch/powerpc/config.mk                             |    2 +
 arch/powerpc/cpu/mpc85xx/spl_minimal.c             |   16 ++
 arch/powerpc/cpu/mpc85xx/u-boot-tpl.lds            |   80 +++++++++
 .../cpu/mpc8xxx/ddr/lc_common_dimm_params.c        |    4 +-
 arch/powerpc/lib/Makefile                          |    2 +
 board/freescale/p1022ds/Makefile                   |    3 +
 board/freescale/p1022ds/spl_minimal.c              |   56 +------
 board/freescale/p1022ds/tlb.c                      |    4 +-
 board/freescale/p1022ds/tpl.c                      |  101 ++++++++++++
 common/Makefile                                    |    9 +
 common/cmd_nvedit.c                                |    8 +-
 config.mk                                          |   32 ++++
 doc/README.TPL                                     |   93 +++++++++++
 drivers/mtd/nand/Makefile                          |    8 +
 drivers/mtd/nand/fsl_elbc_tpl.c                    |  168 ++++++++++++++++++++
 drivers/serial/serial.c                            |    2 +-
 include/bootstage.h                                |    3 +-
 include/configs/P1022DS.h                          |   75 +++++++--
 tpl/Makefile                                       |  161 +++++++++++++++++++
 21 files changed, 824 insertions(+), 83 deletions(-)
 create mode 100644 arch/powerpc/cpu/mpc85xx/u-boot-tpl.lds
 create mode 100644 board/freescale/p1022ds/tpl.c
 create mode 100644 doc/README.TPL
 create mode 100644 drivers/mtd/nand/fsl_elbc_tpl.c
 create mode 100644 tpl/Makefile

diff --git a/Makefile b/Makefile
index ef154aa..65849d1 100644
--- a/Makefile
+++ b/Makefile
@@ -118,10 +118,11 @@ endif # ifneq ($(BUILD_DIR),)
 
 OBJTREE		:= $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
 SPLTREE		:= $(OBJTREE)/spl
+TPLTREE		:= $(OBJTREE)/tpl
 SRCTREE		:= $(CURDIR)
 TOPDIR		:= $(SRCTREE)
 LNDIR		:= $(OBJTREE)
-export	TOPDIR SRCTREE OBJTREE SPLTREE
+export	TOPDIR SRCTREE OBJTREE SPLTREE TPLTREE
 
 MKCONFIG	:= $(SRCTREE)/mkconfig
 export MKCONFIG
@@ -412,9 +413,14 @@ ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
 ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin
 ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin
 ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin
+ALL-$(CONFIG_TPL) += $(obj)tpl/u-boot-tpl.bin
 ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
 ifneq ($(CONFIG_SPL_TARGET),)
 ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET))
+else
+ifneq ($(CONFIG_TPL_TARGET),)
+ALL-$(CONFIG_TPL) += $(obj)$(subst ",,$(CONFIG_TPL_TARGET))
+endif
 endif
 
 # enable combined SPL/u-boot/dtb rules for tegra
@@ -498,6 +504,18 @@ $(obj)u-boot-with-spl.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
 		cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $@
 		rm $(obj)spl/u-boot-spl-pad.bin
 
+$(obj)u-boot-with-tpl.bin: $(obj)spl/u-boot-spl.bin $(obj)tpl/u-boot-tpl.bin \
+		$(obj)u-boot.bin
+		$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(CONFIG_SPL_PAD_TO) \
+			-I binary -O binary \
+			$(obj)spl/u-boot-spl.bin $(obj)spl/u-boot-spl-pad.bin
+		$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(CONFIG_TPL_PAD_TO) \
+			-I binary -O binary \
+			$(obj)tpl/u-boot-tpl.bin $(obj)tpl/u-boot-tpl-pad.bin
+		cat $(obj)spl/u-boot-spl-pad.bin $(obj)tpl/u-boot-tpl-pad.bin \
+			$(obj)u-boot.bin > $@
+		rm $(obj)spl/u-boot-spl-pad.bin $(obj)tpl/u-boot-tpl-pad.bin
+
 $(obj)u-boot-with-spl.imx: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
 		$(MAKE) -C $(SRCTREE)/arch/arm/imx-common \
 			$(OBJTREE)/u-boot-with-spl.imx
@@ -622,6 +640,9 @@ $(obj)u-boot-nand.bin:	nand_spl $(obj)u-boot.bin
 $(obj)spl/u-boot-spl.bin:	$(SUBDIR_TOOLS) depend
 		$(MAKE) -C spl all
 
+$(obj)tpl/u-boot-tpl.bin:	$(SUBDIR_TOOLS)	depend
+		$(MAKE) -C tpl all
+
 updater:
 		$(MAKE) -C tools/updater all
 
@@ -870,6 +891,8 @@ clobber:	tidy
 	@rm -f $(obj)nand_spl/{u-boot-nand_spl.lds,u-boot-spl,u-boot-spl.map}
 	@rm -f $(obj)spl/{u-boot-spl,u-boot-spl.bin,u-boot-spl.map}
 	@rm -f $(obj)spl/u-boot-spl.lds
+	@rm -f $(obj)tpl/{u-boot-tpl,u-boot-tpl.bin,u-boot-tpl.map}
+	@rm -f $(obj)tpl/u-boot-tpl.lds
 	@rm -f $(obj)MLO MLO.byteswap
 	@rm -f $(obj)SPL
 	@rm -f $(obj)tools/xway-swap-bytes
diff --git a/README b/README
index 7add6d4..04f9aa5 100644
--- a/README
+++ b/README
@@ -2985,9 +2985,10 @@ FIT uImage format:
 		Set for the SPL on PPC mpc8xxx targets, support for
 		arch/powerpc/cpu/mpc8xxx/ddr/libddr.o in SPL binary.
 
-		CONFIG_SPL_COMMON_INIT_DDR
+		CONFIG_COMMON_INIT_DDR
 		Set for common ddr init with serial presence detect in
-		SPL binary.
+		SPL binary or TPL binary.
+
 		CONFIG_SYS_NAND_5_ADDR_CYCLE, CONFIG_SYS_NAND_PAGE_COUNT,
 		CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE,
 		CONFIG_SYS_NAND_BLOCK_SIZE, CONFIG_SYS_NAND_BAD_BLOCK_POS,
@@ -3058,6 +3059,56 @@ FIT uImage format:
 		option to re-enable it. This will affect the output of the
 		bootm command when booting a FIT image.
 
+- TPL framework
+		CONFIG_TPL
+		Enable building of TPL globally.
+
+		CONFIG_TPL_LDSCRIPT
+		LDSCRIPT for linking the TPL binary.
+
+		CONFIG_TPL_MAX_SIZE
+		Maximum size of the TPL image (text, data, rodata, and
+		linker lists sections), BSS excluded.
+		When defined, the linker checks that the actual size does
+		not exceed it.
+
+		CONFIG_SPL_TEXT_BASE
+		TEXT_BASE for linking the TPL binary.
+
+		CONFIG_TPL_LIBCOMMON_SUPPORT
+		Support for common/libcommon.o in TPL binary
+
+		CONFIG_TPL_LIBDISK_SUPPORT
+		Support for disk/libdisk.o in TPL binary
+
+		CONFIG_TPL_I2C_SUPPORT
+		Support for drivers/i2c/libi2c.o in TPL binary
+
+		CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
+		Set for the TPL on PPC mpc8xxx targets, support for
+		arch/powerpc/cpu/mpc8xxx/ddr/libddr.o in TPL binary.
+
+		CONFIG_TPL_SERIAL_SUPPORT
+		Support for drivers/serial/libserial.o in TPL binary
+
+		CONFIG_TPL_LIBGENERIC_SUPPORT
+		Support for lib/libgeneric.o in TPL binary
+
+		CONFIG_TPL_ENV_SUPPORT
+		Support for the environment operating in TPL binary
+
+		CONFIG_TPL_PAD_TO
+		Image offset to which the TPL should be padded before appending
+		the TPL payload. By default, this is defined as
+		CONFIG_TPL_MAX_SIZE, or 0 if CONFIG_TPL_MAX_SIZE is undefined.
+		CONFIG_TPL_PAD_TO must be either 0, meaning to append the TPL
+		payload without any padding, or >= CONFIG_TPL_MAX_SIZE.
+
+		CONFIG_TPL_TARGET
+		Final target image containing SPL and payload.  Some TPLs
+		use an arch-specific makefile fragment instead, for
+		example if more than one image needs to be produced.
+
 Modem Support:
 --------------
 
diff --git a/arch/powerpc/config.mk b/arch/powerpc/config.mk
index e32d2bf..aebb0aa 100644
--- a/arch/powerpc/config.mk
+++ b/arch/powerpc/config.mk
@@ -48,5 +48,7 @@ endif
 
 # Only test once
 ifneq ($(CONFIG_SPL_BUILD),y)
+ifneq ($(CONFIG_TPL_BUILD),y)
 ALL-y += checkgcc4
 endif
+endif
diff --git a/arch/powerpc/cpu/mpc85xx/spl_minimal.c b/arch/powerpc/cpu/mpc85xx/spl_minimal.c
index c6b9cd0..a2d9417 100644
--- a/arch/powerpc/cpu/mpc85xx/spl_minimal.c
+++ b/arch/powerpc/cpu/mpc85xx/spl_minimal.c
@@ -30,8 +30,19 @@ DECLARE_GLOBAL_DATA_PTR;
 
 void cpu_init_f(void)
 {
+#if defined(CONFIG_SYS_NAND_BR_PRELIM) && defined(CONFIG_SYS_NAND_OR_PRELIM)
+	set_lbc_br(0, CONFIG_SYS_NAND_BR_PRELIM);
+	set_lbc_or(0, CONFIG_SYS_NAND_OR_PRELIM);
+#endif
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+	set_lbc_or(2, CONFIG_SYS_OR2_PRELIM);
+	set_lbc_br(2, CONFIG_SYS_BR2_PRELIM);
+#endif
+
 #ifdef CONFIG_SYS_INIT_L2_ADDR
 	ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+	char *l2srbar;
+	int i;
 
 	out_be32(&l2cache->l2srbar0, CONFIG_SYS_INIT_L2_ADDR);
 
@@ -42,6 +53,11 @@ void cpu_init_f(void)
 	/* set L2E=1 & L2SRAM=001 */
 	out_be32(&l2cache->l2ctl,
 		(MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+
+	/* Initialize L2 SRAM to zero */
+	l2srbar = (char *)CONFIG_SYS_INIT_L2_ADDR;
+	for (i = 0; i < CONFIG_SYS_L2_SIZE; i++)
+		l2srbar[i] = 0;
 #endif
 }
 
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-tpl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-tpl.lds
new file mode 100644
index 0000000..344c325
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-tpl.lds
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 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 "config.h"	/* CONFIG_BOARDDIR */
+
+OUTPUT_ARCH(powerpc)
+PHDRS
+{
+	text PT_LOAD;
+	bss PT_LOAD;
+}
+SECTIONS
+{
+	. = CONFIG_TPL_TEXT_BASE;
+	.text : {
+		*(.text*)
+	}
+	_etext = .;
+
+	.reloc : {
+		_GOT2_TABLE_ = .;
+		KEEP(*(.got2))
+		KEEP(*(.got))
+		PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+		_FIXUP_TABLE_ = .;
+		KEEP(*(.fixup))
+	}
+	__got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+	__fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+	. = ALIGN(8);
+	.data : {
+		*(.rodata*)
+		*(.data*)
+		*(.sdata*)
+	}
+	_edata  =  .;
+
+	. = .;
+	__start___ex_table = .;
+	__ex_table : { *(__ex_table) }
+	__stop___ex_table = .;
+
+	. = ALIGN(8);
+	__init_begin = .;
+	__init_end = .;
+
+	.bootpg ADDR(.text) - 0x1000 :
+	{
+		KEEP(*(.bootpg))
+	} :text = 0xffff
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : {
+		*(.sbss*)
+		*(.bss*)
+	}
+	. = ALIGN(4);
+	__bss_end = .;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
index 56128a7..e46100a 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
@@ -218,13 +218,13 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 		if (dimm_params[i].n_ranks) {
 			if (dimm_params[i].registered_dimm) {
 				temp1 = 1;
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 				printf("Detected RDIMM %s\n",
 					dimm_params[i].mpart);
 #endif
 			} else {
 				temp2 = 1;
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 				printf("Detected UDIMM %s\n",
 					dimm_params[i].mpart);
 #endif
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 59c723b..c61eb06 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -59,10 +59,12 @@ SOBJS-y	+= reloc.o
 
 COBJS-$(CONFIG_BAT_RW) += bat_rw.o
 ifndef CONFIG_SPL_BUILD
+ifndef CONFIG_TPL_BUILD
 ifndef CONFIG_SYS_GENERIC_BOARD
 COBJS-y	+= board.o
 endif
 endif
+endif
 COBJS-y	+= bootm.o
 COBJS-y	+= cache.o
 COBJS-y	+= extable.o
diff --git a/board/freescale/p1022ds/Makefile b/board/freescale/p1022ds/Makefile
index 9746063..58f224e 100644
--- a/board/freescale/p1022ds/Makefile
+++ b/board/freescale/p1022ds/Makefile
@@ -27,6 +27,9 @@ else
 ifdef CONFIG_SPL_BUILD
 COBJS-y += spl.o
 endif
+ifdef CONFIG_TPL_BUILD
+COBJS-y += tpl.o
+endif
 COBJS-y	+= $(BOARD).o
 COBJS-y	+= ddr.o
 COBJS-y	+= law.o
diff --git a/board/freescale/p1022ds/spl_minimal.c b/board/freescale/p1022ds/spl_minimal.c
index 8d12fa6..8c3acfe 100644
--- a/board/freescale/p1022ds/spl_minimal.c
+++ b/board/freescale/p1022ds/spl_minimal.c
@@ -27,51 +27,6 @@
 #include <asm/fsl_ddr_sdram.h>
 
 
-/*
- * Fixed sdram init -- doesn't use serial presence detect.
- */
-void sdram_init(void)
-{
-	volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
-
-	__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
-	__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
-#if CONFIG_CHIP_SELECTS_PER_CTRL > 1
-	__raw_writel(CONFIG_SYS_DDR_CS1_BNDS, &ddr->cs1_bnds);
-	__raw_writel(CONFIG_SYS_DDR_CS1_CONFIG, &ddr->cs1_config);
-#endif
-	__raw_writel(CONFIG_SYS_DDR_TIMING_3, &ddr->timing_cfg_3);
-	__raw_writel(CONFIG_SYS_DDR_TIMING_0, &ddr->timing_cfg_0);
-	__raw_writel(CONFIG_SYS_DDR_TIMING_1, &ddr->timing_cfg_1);
-	__raw_writel(CONFIG_SYS_DDR_TIMING_2, &ddr->timing_cfg_2);
-
-	__raw_writel(CONFIG_SYS_DDR_CONTROL_2, &ddr->sdram_cfg_2);
-	__raw_writel(CONFIG_SYS_DDR_MODE_1, &ddr->sdram_mode);
-	__raw_writel(CONFIG_SYS_DDR_MODE_2, &ddr->sdram_mode_2);
-
-	__raw_writel(CONFIG_SYS_DDR_INTERVAL, &ddr->sdram_interval);
-	__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
-	__raw_writel(CONFIG_SYS_DDR_CLK_CTRL, &ddr->sdram_clk_cntl);
-
-	__raw_writel(CONFIG_SYS_DDR_TIMING_4, &ddr->timing_cfg_4);
-	__raw_writel(CONFIG_SYS_DDR_TIMING_5, &ddr->timing_cfg_5);
-	__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
-	__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL, &ddr->ddr_wrlvl_cntl);
-
-	/* Set, but do not enable the memory */
-	__raw_writel(CONFIG_SYS_DDR_CONTROL & ~SDRAM_CFG_MEM_EN,
-			&ddr->sdram_cfg);
-
-	in_be32(&ddr->sdram_cfg);
-	udelay(500);
-
-	/* Let the controller go */
-	out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
-	in_be32(&ddr->sdram_cfg);
-
-	set_next_law(0, CONFIG_SYS_SDRAM_SIZE_LAW, LAW_TRGT_IF_DDR_1);
-}
-
 const static u32 sysclk_tbl[] = {
 	66666000, 7499900, 83332500, 8999900,
 	99999000, 11111000, 12499800, 13333200
@@ -83,9 +38,6 @@ void board_init_f(ulong bootflag)
 	u32 plat_ratio, sys_clk, bus_clk;
 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
 
-	/* for FPGA */
-	set_lbc_br(2, CONFIG_SYS_BR2_PRELIM);
-	set_lbc_or(2, CONFIG_SYS_OR2_PRELIM);
 
 	/* initialize selected port with appropriate baud rate */
 	px_spd = in_8((unsigned char *)(PIXIS_BASE + PIXIS_SPD));
@@ -98,19 +50,17 @@ void board_init_f(ulong bootflag)
 
 	puts("\nNAND boot... ");
 
-	/* Initialize the DDR3 */
-	sdram_init();
-
 	/* copy code to RAM and jump to it - this should not return */
 	/* NOTE - code has to be copied out of NAND buffer before
 	 * other blocks can be read.
 	 */
-	relocate_code(CONFIG_SPL_RELOC_STACK, 0,
-			CONFIG_SPL_RELOC_TEXT_BASE);
+	relocate_code(CONFIG_SYS_NAND_U_BOOT_RELOC_SP, 0,
+			CONFIG_SYS_NAND_U_BOOT_RELOC);
 }
 
 void board_init_r(gd_t *gd, ulong dest_addr)
 {
+	puts("\nSecond program loader running in sram...");
 	nand_boot();
 }
 
diff --git a/board/freescale/p1022ds/tlb.c b/board/freescale/p1022ds/tlb.c
index 9b14c37..aed8b86 100644
--- a/board/freescale/p1022ds/tlb.c
+++ b/board/freescale/p1022ds/tlb.c
@@ -41,7 +41,7 @@ struct fsl_e_tlb_entry tlb_table[] = {
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 1, BOOKE_PAGESZ_1M, 1),
 
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 	/* W**G* - Flash/promjet, localbus */
 	/* This will be changed to *I*G* after relocation to RAM. */
 	SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
@@ -75,7 +75,7 @@ struct fsl_e_tlb_entry tlb_table[] = {
 		      0, 7, BOOKE_PAGESZ_4K, 1),
 
 #if defined(CONFIG_SYS_RAMBOOT) || \
-	(defined(CONFIG_SPL) && !defined(CONFIG_SPL_COMMON_INIT_DDR))
+	(defined(CONFIG_SPL) && !defined(CONFIG_COMMON_INIT_DDR))
 	/* **** - eSDHC/eSPI/NAND boot */
 	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
 			MAS3_SX|MAS3_SW|MAS3_SR, 0,
diff --git a/board/freescale/p1022ds/tpl.c b/board/freescale/p1022ds/tpl.c
new file mode 100644
index 0000000..de1aa03
--- /dev/null
+++ b/board/freescale/p1022ds/tpl.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * 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 <ns16550.h>
+#include <malloc.h>
+#include <i2c.h>
+#include "../common/ngpixis.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const u32 sysclk_tbl[] = {
+	66666000, 7499900, 83332500, 8999900,
+	99999000, 11111000, 12499800, 13333200
+};
+
+ulong get_effective_memsize(void)
+{
+	return CONFIG_SYS_L2_SIZE;
+}
+
+void board_init_f(ulong bootflag)
+{
+	int px_spd;
+	u32 plat_ratio, sys_clk, bus_clk;
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	console_init_f();
+	/* Set pmuxcr to allow both i2c1 and i2c2 */
+	setbits_be32(&gur->pmuxcr, in_be32(&gur->pmuxcr) | 0x1000);
+	setbits_be32(&gur->pmuxcr,
+		in_be32(&gur->pmuxcr) | MPC85xx_PMUXCR_SD_DATA);
+
+	/* Read back the register to synchronize the write. */
+	in_be32(&gur->pmuxcr);
+
+	/* initialize selected port with appropriate baud rate */
+	px_spd = in_8((unsigned char *)(PIXIS_BASE + PIXIS_SPD));
+	sys_clk = sysclk_tbl[px_spd & PIXIS_SPD_SYSCLK_MASK];
+	plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
+	bus_clk = sys_clk * plat_ratio / 2;
+
+	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+			bus_clk / 16 / CONFIG_BAUDRATE);
+	/* copy code to RAM and jump to it - this should not return */
+	/* NOTE - code has to be copied out of NAND buffer before
+	 * other blocks can be read.
+	 */
+	relocate_code(CONFIG_TPL_RELOC_STACK, 0,
+			CONFIG_TPL_RELOC_TEXT_BASE);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *)CONFIG_TPL_GD_ADDR;
+	bd_t *bd;
+
+	memset(gd, 0, sizeof(gd_t));
+	bd = (bd_t *)(CONFIG_TPL_GD_ADDR + sizeof(gd_t));
+	memset(bd, 0, sizeof(bd_t));
+	gd->bd = bd;
+	bd->bi_memstart = CONFIG_SYS_INIT_L2_ADDR;
+	bd->bi_memsize = CONFIG_SYS_L2_SIZE;
+
+	probecpu();
+	get_clocks();
+	mem_malloc_init(CONFIG_TPL_RELOC_MALLOC_ADDR, \
+			CONFIG_TPL_RELOC_MALLOC_SIZE);
+        /* relocate environment function pointers etc. */
+	nand_load(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+		(uchar *)CONFIG_ENV_ADDR);
+
+	gd->env_addr  = (ulong)(CONFIG_ENV_ADDR);
+        gd->env_valid = 1;
+
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	gd->ram_size = initdram(0);
+	puts("Tertiary program loader running in sram...");
+
+	nand_boot();
+}
diff --git a/common/Makefile b/common/Makefile
index 3581603..7976adb 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -27,6 +27,7 @@ LIB	= $(obj)libcommon.o
 
 # core
 ifndef CONFIG_SPL_BUILD
+ifndef CONFIG_TPL_BUILD
 COBJS-y += main.o
 COBJS-y += command.o
 COBJS-y += exports.o
@@ -204,6 +205,7 @@ COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
 COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
 COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o
 endif
+endif
 
 ifdef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
@@ -223,6 +225,13 @@ else
 COBJS-y += env_nowhere.o
 endif
 endif
+
+ifdef CONFIG_TPL_BUILD
+COBJS-$(CONFIG_TPL_ENV_SUPPORT) += env_attr.o
+COBJS-$(CONFIG_TPL_ENV_SUPPORT) += env_flags.o
+COBJS-$(CONFIG_TPL_ENV_SUPPORT) += env_callback.o
+endif
+
 # core command
 COBJS-y += cmd_nvedit.o
 #environment
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 2478c95..d91a2ef 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -87,7 +87,7 @@ int get_env_id(void)
 	return env_id;
 }
 
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 /*
  * Command interface: print one or all environment variables
  *
@@ -356,7 +356,7 @@ ulong getenv_hex(const char *varname, ulong default_val)
 	return value;
 }
 
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 static int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	if (argc < 2)
@@ -700,7 +700,7 @@ ulong getenv_ulong(const char *name, int base, ulong default_val)
 	return str ? simple_strtoul(str, NULL, base) : default_val;
 }
 
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
 static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc,
 		       char * const argv[])
@@ -741,7 +741,7 @@ int envmatch(uchar *s1, int i2)
 	return -1;
 }
 
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
 			  int argc, char * const argv[])
 {
diff --git a/config.mk b/config.mk
index ddf350e..484daf5 100644
--- a/config.mk
+++ b/config.mk
@@ -41,8 +41,12 @@ ifneq ($(OBJTREE),$(SRCTREE))
 ifeq ($(CONFIG_SPL_BUILD),y)
 obj := $(if $(dir),$(SPLTREE)/$(dir)/,$(SPLTREE)/)
 else
+ifeq ($(CONFIG_TPL_BUILD),y)
+obj := $(if $(dir),$(TPLTREE)/$(dir)/,$(TPLTREE)/)
+else
 obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
 endif
+endif
 src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
 
 $(shell mkdir -p $(obj))
@@ -53,8 +57,14 @@ obj := $(if $(dir),$(SPLTREE)/$(dir)/,$(SPLTREE)/)
 
 $(shell mkdir -p $(obj))
 else
+ifeq ($(CONFIG_TPL_BUILD),y)
+obj := $(if $(dir),$(TPLTREE)/$(dir)/,$(TPLTREE)/)
+
+$(shell mkdir -p $(obj))
+else
 obj :=
 endif
+endif
 src :=
 endif
 
@@ -210,6 +220,11 @@ CPPFLAGS += -ffunction-sections -fdata-sections
 LDFLAGS_FINAL += --gc-sections
 endif
 
+ifeq ($(CONFIG_TPL_BUILD),y)
+CPPFLAGS += -ffunction-sections -fdata-sections
+LDFLAGS_FINAL += --gc-sections
+endif
+
 ifneq ($(CONFIG_SYS_TEXT_BASE),)
 CPPFLAGS += -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE)
 endif
@@ -218,10 +233,18 @@ ifneq ($(CONFIG_SPL_TEXT_BASE),)
 CPPFLAGS += -DCONFIG_SPL_TEXT_BASE=$(CONFIG_SPL_TEXT_BASE)
 endif
 
+ifneq ($(CONFIG_TPL_TEXT_BASE),)
+CPPFLAGS += -DCONFIG_TPL_TEXT_BASE=$(CONFIG_TPL_TEXT_BASE)
+endif
+
 ifneq ($(CONFIG_SPL_PAD_TO),)
 CPPFLAGS += -DCONFIG_SPL_PAD_TO=$(CONFIG_SPL_PAD_TO)
 endif
 
+ifneq ($(CONFIG_TPL_PAD_TO),)
+CPPFLAGS += -DCONFIG_TPL_PAD_TO=$(CONFIG_TPL_PAD_TO)
+endif
+
 ifneq ($(CONFIG_UBOOT_PAD_TO),)
 CPPFLAGS += -DCONFIG_UBOOT_PAD_TO=$(CONFIG_UBOOT_PAD_TO)
 endif
@@ -230,6 +253,10 @@ ifeq ($(CONFIG_SPL_BUILD),y)
 CPPFLAGS += -DCONFIG_SPL_BUILD
 endif
 
+ifeq ($(CONFIG_TPL_BUILD),y)
+CPPFLAGS += -DCONFIG_TPL_BUILD
+endif
+
 # Does this architecture support generic board init?
 ifeq ($(__HAVE_ARCH_GENERIC_BOARD),)
 ifneq ($(CONFIG_SYS_GENERIC_BOARD),)
@@ -294,6 +321,11 @@ ifneq ($(CONFIG_SPL_TEXT_BASE),)
 LDFLAGS_u-boot-spl += -Ttext $(CONFIG_SPL_TEXT_BASE)
 endif
 
+LDFLAGS_u-boot-tpl += -T $(obj)u-boot-tpl.lds $(LDFLAGS_FINAL)
+ifneq ($(CONFIG_TPL_TEXT_BASE),)
+LDFLAGS_u-boot-tpl += -Ttext $(CONFIG_TPL_TEXT_BASE)
+endif
+
 # Linus' kernel sanity checking tool
 CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
                   -Wbitwise -Wno-return-void -D__CHECK_ENDIAN__ $(CF)
diff --git a/doc/README.TPL b/doc/README.TPL
new file mode 100644
index 0000000..6703f1a
--- /dev/null
+++ b/doc/README.TPL
@@ -0,0 +1,93 @@
+Generic TPL framework
+=====================
+
+Overview
+--------
+
+Due to the SPL on some boards(powerpc mpc85xx) has a size limit and cannot
+be compatible with all the external device(e.g. DDR). So add a tertiary
+program loader (TPL) to enable a loader stub that runs in the L2 SRAM, 
+after being loaded by the code from the SPL. It loads the final uboot image
+into DDR, then jump to it to begin execution. Now, only the powerpc mpc85xx
+has this requirement and will implemente it.
+
+Keep consistent with SPL, with this framework almost all source files for a
+board can be reused. No code duplication or symlinking is necessary anymore.
+
+How it works
+------------
+
+There is a new directory TOPDIR/tpl which contains only a Makefile.
+The object files are built separately for TPL and placed in this directory.
+The final binaries which are generated are u-boot-tpl, u-boot-tpl.bin and
+u-boot-tpl.map.
+
+During the TPL build a variable named CONFIG_TPL_BUILD is exported
+in the make environment and also appended to CPPFLAGS with -DCONFIG_TPL_BUILD.
+Source files can therefore be compiled for TPL with different settings.
+
+For example:
+
+ifeq ($(CONFIG_TPL_BUILD),y)
+COBJS-y += board_tpl.o
+else
+COBJS-y += board.o
+endif
+
+COBJS-$(CONFIG_TPL_BUILD) += foo.o
+
+#ifdef CONFIG_TPL_BUILD
+	foo();
+#endif
+
+
+The building of TPL images can be with:
+
+#define CONFIG_TPL
+
+Because TPL images normally have a different text base, one has to be
+configured by defining CONFIG_TPL_TEXT_BASE. The linker script has to be
+defined with CONFIG_TPL_LDSCRIPT.
+
+To support generic U-Boot libraries and drivers in the TPL binary one can
+optionally define CONFIG_TPL_XXX_SUPPORT. Currently following options
+are supported:
+
+CONFIG_TPL_LIBCOMMON_SUPPORT (common/libcommon.o)
+CONFIG_TPL_LIBDISK_SUPPORT (disk/libdisk.o)
+CONFIG_TPL_I2C_SUPPORT (drivers/i2c/libi2c.o)
+CONFIG_TPL_GPIO_SUPPORT (drivers/gpio/libgpio.o)
+CONFIG_TPL_MMC_SUPPORT (drivers/mmc/libmmc.o)
+CONFIG_TPL_SERIAL_SUPPORT (drivers/serial/libserial.o)
+CONFIG_TPL_SPI_FLASH_SUPPORT (drivers/mtd/spi/libspi_flash.o)
+CONFIG_TPL_SPI_SUPPORT (drivers/spi/libspi.o)
+CONFIG_TPL_FAT_SUPPORT (fs/fat/libfat.o)
+CONFIG_TPL_LIBGENERIC_SUPPORT (lib/libgeneric.o)
+CONFIG_TPL_POWER_SUPPORT (drivers/power/libpower.o)
+CONFIG_TPL_NAND_SUPPORT (drivers/mtd/nand/libnand.o)
+CONFIG_TPL_DMA_SUPPORT (drivers/dma/libdma.o)
+CONFIG_TPL_POST_MEM_SUPPORT (post/drivers/memory.o)
+
+
+
+Estimating stack usage
+----------------------
+
+With gcc 4.6 (and later) and the use of GNU cflow it is possible to estimate
+stack usage at various points in run sequence of TPL.  The -fstack-usage option
+to gcc will produce '.su' files (such as arch/arm/cpu/armv7/syslib.su) that
+will give stack usage information and cflow can construct program flow.
+
+Must have gcc 4.6 or later, which supports -fstack-usage
+
+1) Build normally
+2) Perform the following shell command to generate a list of C files used in
+TPL:
+$ find tpl -name '*.su' | sed -e 's:^tpl/::' -e 's:[.]su$:.c:' > used-tpl.list
+3) Execute cflow:
+$ cflow --main=board_init_r `cat used-tpl.list` 2>&1 | $PAGER
+
+cflow will spit out a number of warnings as it does not parse
+the config files and picks functions based on #ifdef.  Parsing the '.i'
+files instead introduces another set of headaches.  These warnings are
+not usually important to understanding the flow, however.
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 8821704..35e979e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -42,6 +42,8 @@ COBJS-$(CONFIG_SPL_NAND_BASE) += nand_base.o
 
 else # not spl
 
+ifndef CONFIG_TPL_BUILD
+
 NORMAL_DRIVERS=y
 
 COBJS-y += nand.o
@@ -51,6 +53,7 @@ COBJS-y += nand_util.o
 COBJS-y += nand_ecc.o
 COBJS-y += nand_base.o
 
+endif # not tpl
 endif # not spl
 
 ifdef NORMAL_DRIVERS
@@ -82,8 +85,13 @@ COBJS-$(CONFIG_NAND_DOCG4) += docg4.o
 
 else  # minimal SPL drivers
 
+ifdef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand_spl.o
+endif
+ifdef CONFIG_TPL_BUILD
+COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_tpl.o
+endif
 
 endif # drivers
 endif # nand
diff --git a/drivers/mtd/nand/fsl_elbc_tpl.c b/drivers/mtd/nand/fsl_elbc_tpl.c
new file mode 100644
index 0000000..09868c4
--- /dev/null
+++ b/drivers/mtd/nand/fsl_elbc_tpl.c
@@ -0,0 +1,168 @@
+/*
+ * 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/fsl_lbc.h>
+#include <nand.h>
+
+#define WINDOW_SIZE 8192
+
+static void nand_wait(void)
+{
+	fsl_lbc_t *regs = LBC_BASE_ADDR;
+
+	for (;;) {
+		uint32_t status = in_be32(&regs->ltesr);
+
+		if (status == 1)
+			return;
+
+		if (status & 1) {
+			puts("read failed (ltesr)\n");
+			for (;;);
+		}
+	}
+}
+
+int nand_load(uint32_t offs, unsigned int uboot_size, void *vdst)
+{
+	fsl_lbc_t *regs = LBC_BASE_ADDR;
+	uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
+	const int large = CONFIG_SYS_NAND_OR_PRELIM & OR_FCM_PGS;
+	const int block_shift = large ? 17 : 14;
+	const int block_size = 1 << block_shift;
+	const int page_size = large ? 2048 : 512;
+	const int bad_marker = large ? page_size + 0 : page_size + 5;
+	int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2;
+	int pos = 0;
+	char *dst = vdst;
+
+	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)) && (pos < uboot_size));
+	}
+
+	return 0;
+}
+
+/*
+ * 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);
+	/*
+	 * Load U-Boot image from NAND into RAM
+	 */
+	nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS,
+			CONFIG_SYS_NAND_U_BOOT_SIZE,
+			(void *)CONFIG_SYS_NAND_U_BOOT_DST);
+
+#ifdef CONFIG_NAND_ENV_DST
+	nand_load(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+			(void *)CONFIG_NAND_ENV_DST);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	nand_load(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
+			(void *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
+#endif
+#endif
+
+#ifdef CONFIG_SPL_FLUSH_IMAGE
+	/*
+	 * Clean d-cache and invalidate i-cache, to
+	 * make sure that no stale data is executed.
+	 */
+	flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
+#endif
+
+	puts("transfering control\n");
+	/*
+	 * Jump to U-Boot image
+	 */
+	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
+	(*uboot)();
+}
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index daa8003..81aca81 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -371,7 +371,7 @@ static struct serial_device *get_current(void)
 
 	/* We must have a console device */
 	if (!dev) {
-#ifdef CONFIG_SPL_BUILD
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
 		puts("Cannot find console\n");
 		hang();
 #else
diff --git a/include/bootstage.h b/include/bootstage.h
index ef07a87..1e8c492 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -220,7 +220,8 @@ enum bootstage_id {
  */
 ulong timer_get_boot_us(void);
 
-#if !defined(CONFIG_SPL_BUILD) && !defined(USE_HOSTCC)
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && \
+	!defined(USE_HOSTCC)
 /*
  * Board code can implement show_boot_progress() if needed.
  *
diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h
index 94026a5..ea4bc18 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -43,7 +43,7 @@
 #define CONFIG_SYS_LDSCRIPT		"arch/powerpc/cpu/mpc85xx/u-boot.lds"
 #define CONFIG_SPL_MMC_BOOT
 #ifdef CONFIG_SPL_BUILD
-#define CONFIG_SPL_COMMON_INIT_DDR
+#define CONFIG_COMMON_INIT_DDR
 #endif
 #endif
 
@@ -73,7 +73,7 @@
 #define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot.lds"
 #define CONFIG_SPL_SPI_BOOT
 #ifdef CONFIG_SPL_BUILD
-#define CONFIG_SPL_COMMON_INIT_DDR
+#define CONFIG_COMMON_INIT_DDR
 #endif
 #endif
 
@@ -81,25 +81,41 @@
 
 #ifdef CONFIG_NAND
 #define CONFIG_SPL
+#define CONFIG_TPL
 #define CONFIG_SPL_INIT_MINIMAL
 #define CONFIG_SPL_SERIAL_SUPPORT
 #define CONFIG_SPL_NAND_SUPPORT
 #define CONFIG_SPL_FLUSH_IMAGE
-#define CONFIG_SPL_TARGET              "u-boot-with-spl.bin"
-
-#define CONFIG_SYS_TEXT_BASE           0x00201000
-#define CONFIG_SPL_TEXT_BASE           0xfffff000
-#define CONFIG_SPL_MAX_SIZE            4096
-#define CONFIG_SPL_RELOC_TEXT_BASE     0x00100000
-#define CONFIG_SPL_RELOC_STACK         0x00100000
-#define CONFIG_SYS_NAND_U_BOOT_SIZE    ((512 << 10) + CONFIG_SPL_MAX_SIZE)
-#define CONFIG_SYS_NAND_U_BOOT_DST     (0x00200000 - CONFIG_SPL_MAX_SIZE)
-#define CONFIG_SYS_NAND_U_BOOT_START   0x00200000
-#define CONFIG_SYS_NAND_U_BOOT_OFFS    0
-#define CONFIG_SYS_LDSCRIPT            "arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
+#define CONFIG_SPL_TEXT_BASE		0xff800000
+#define CONFIG_SPL_MAX_SIZE		4096
+#define CONFIG_SPL_PAD_TO		0x20000
 #ifdef CONFIG_SPL_BUILD
 #define CONFIG_SPL_MINIMAL
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	(128 << 10)
+#define CONFIG_SYS_NAND_U_BOOT_DST	0xf8f80000
+#define CONFIG_SYS_NAND_U_BOOT_START	0xf8f80000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	(128 << 10)
+#endif
+#define CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
+#define CONFIG_TPL_ENV_SUPPORT
+#define CONFIG_TPL_SERIAL_SUPPORT
+#define CONFIG_TPL_LIBGENERIC_SUPPORT
+#define CONFIG_TPL_LIBCOMMON_SUPPORT
+#define CONFIG_TPL_I2C_SUPPORT
+#define CONFIG_TPL_NAND_SUPPORT
+#define CONFIG_TPL_TEXT_BASE		0xf8f81000
+#define CONFIG_TPL_MAX_SIZE		(128 << 10)
+#define CONFIG_TPL_PAD_TO		0x20000
+#ifdef CONFIG_TPL_BUILD
+#define CONFIG_COMMON_INIT_DDR
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	(576 << 10)
+#define CONFIG_SYS_NAND_U_BOOT_DST	(0x11000000)
+#define CONFIG_SYS_NAND_U_BOOT_START	(0x11000000)
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	((128 + 128) << 10)
 #endif
+#define CONFIG_SYS_TEXT_BASE		0x11001000
+#define CONFIG_SYS_LDSCRIPT		"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
+#define CONFIG_TPL_TARGET		"u-boot-with-tpl.bin"
 #endif
 
 /* High Level Configuration Options */
@@ -154,7 +170,7 @@
 
 /* IN case of NAND bootloader relocate CCSRBAR in RAMboot code not in the 4k
        SPL code*/
-#ifdef CONFIG_SPL_BUILD
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
 #define CONFIG_SYS_CCSR_DO_NOT_RELOCATE
 #endif
 
@@ -255,6 +271,8 @@
 #ifndef CONFIG_SYS_MONITOR_BASE
 #ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SPL_TEXT_BASE
+#elif defined(CONFIG_TPL_BUILD)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_TPL_TEXT_BASE
 #else
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE	/* start of monitor */
 #endif
@@ -336,7 +354,7 @@
 	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
 #define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
 
-#define CONFIG_SYS_MONITOR_LEN		(512 * 1024)
+#define CONFIG_SYS_MONITOR_LEN		(576 * 1024)
 #define CONFIG_SYS_MALLOC_LEN		(10 * 1024 * 1024)
 
 /*
@@ -354,7 +372,25 @@
 #define CONFIG_SPL_RELOC_MALLOC_ADDR	(CONFIG_SYS_INIT_L2_ADDR + 160 * 1024)
 #define CONFIG_SPL_RELOC_MALLOC_SIZE	(96 << 10)
 #define CONFIG_SPL_GD_ADDR		(CONFIG_SYS_INIT_L2_ADDR + 112 * 1024)
+#elif defined(CONFIG_NAND)
+#define CONFIG_SYS_INIT_L2_ADDR		0xf8f80000
+#define CONFIG_SYS_INIT_L2_ADDR_PHYS	CONFIG_SYS_INIT_L2_ADDR
+#define CONFIG_SYS_L2_SIZE		(256 << 10)
+#define CONFIG_SYS_INIT_L2_END	(CONFIG_SYS_INIT_L2_ADDR + CONFIG_SYS_L2_SIZE)
+#define CONFIG_SYS_NAND_U_BOOT_RELOC	(CONFIG_SYS_INIT_L2_END - 0x2000)
+#define CONFIG_SYS_NAND_U_BOOT_RELOC_SP	((CONFIG_SYS_INIT_L2_END - 1) & ~0xF)
 #endif
+#elif defined(CONFIG_TPL_BUILD)
+#define CONFIG_SYS_INIT_L2_ADDR		0xf8f80000
+#define CONFIG_SYS_INIT_L2_ADDR_PHYS	CONFIG_SYS_INIT_L2_ADDR
+#define CONFIG_SYS_L2_SIZE		(256 << 10)
+#define CONFIG_SYS_INIT_L2_END	(CONFIG_SYS_INIT_L2_ADDR + CONFIG_SYS_L2_SIZE)
+#define CONFIG_TPL_RELOC_TEXT_BASE	0xf8f81000
+#define CONFIG_TPL_RELOC_STACK		(CONFIG_SYS_INIT_L2_ADDR + 192 * 1024)
+#define CONFIG_TPL_RELOC_STACK_SIZE	(16 << 10)
+#define CONFIG_TPL_RELOC_MALLOC_ADDR	(CONFIG_SYS_INIT_L2_ADDR + 208 * 1024)
+#define CONFIG_TPL_RELOC_MALLOC_SIZE	(48 << 10)
+#define CONFIG_TPL_GD_ADDR		(CONFIG_SYS_INIT_L2_ADDR + 176 * 1024)
 #endif
 
 
@@ -604,8 +640,13 @@
 #define CONFIG_SYS_MMC_ENV_DEV	0
 #elif defined(CONFIG_NAND)
 #define CONFIG_ENV_IS_IN_NAND
+#ifdef CONFIG_TPL_BUILD
+#define CONFIG_ENV_SIZE		0x2000
+#define CONFIG_ENV_ADDR		(CONFIG_SYS_INIT_L2_ADDR + (160 << 10))
+#else
 #define CONFIG_ENV_SIZE		CONFIG_SYS_NAND_BLOCK_SIZE
-#define CONFIG_ENV_OFFSET	((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
+#endif
+#define CONFIG_ENV_OFFSET	(1024 * 1024)
 #define CONFIG_ENV_RANGE	(3 * CONFIG_ENV_SIZE)
 #elif defined(CONFIG_SYS_RAMBOOT)
 #define CONFIG_ENV_IS_NOWHERE	/* Store ENV in memory only */
diff --git a/tpl/Makefile b/tpl/Makefile
new file mode 100644
index 0000000..49e95a9
--- /dev/null
+++ b/tpl/Makefile
@@ -0,0 +1,161 @@
+#
+# Copyright 2013 Freescale Semiconductor, Inc.
+#
+# 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.
+#
+
+CONFIG_TPL_BUILD := y
+export CONFIG_TPL_BUILD
+
+include $(TOPDIR)/config.mk
+
+# We want the final binaries in this directory
+obj := $(OBJTREE)/tpl/
+
+HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(SRCTREE)/board/$(VENDOR)/common/Makefile),y,n)
+
+ifdef	CONFIG_TPL_START_S_PATH
+START_PATH := $(subst ",,$(CONFIG_TPL_START_S_PATH))
+else
+START_PATH := $(CPUDIR)
+endif
+
+START := $(START_PATH)/start.o
+ifeq ($(CPU),x86)
+START += $(START_PATH)/start16.o
+START += $(START_PATH)/resetvec.o
+endif
+ifeq ($(CPU),ppc4xx)
+START += $(START_PATH)/resetvec.o
+endif
+ifeq ($(CPU),mpc85xx)
+START += $(START_PATH)/resetvec.o
+endif
+
+LIBS-y += arch/$(ARCH)/lib/lib$(ARCH).o
+
+LIBS-y += $(CPUDIR)/lib$(CPU).o
+ifeq ($(CPU),mpc83xx)
+LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
+endif
+ifeq ($(CPU),mpc85xx)
+LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
+ifdef CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT
+LIBS-y += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
+endif
+endif
+ifeq ($(CPU),mpc86xx)
+LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
+endif
+
+ifdef SOC
+LIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).o
+endif
+LIBS-y += board/$(BOARDDIR)/lib$(BOARD).o
+LIBS-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/lib$(VENDOR).o
+
+LIBS-$(CONFIG_TPL_LIBCOMMON_SUPPORT) += common/libcommon.o
+LIBS-$(CONFIG_TPL_LIBDISK_SUPPORT) += disk/libdisk.o
+LIBS-$(CONFIG_TPL_I2C_SUPPORT) += drivers/i2c/libi2c.o
+LIBS-$(CONFIG_TPL_GPIO_SUPPORT) += drivers/gpio/libgpio.o
+LIBS-$(CONFIG_TPL_MMC_SUPPORT) += drivers/mmc/libmmc.o
+LIBS-$(CONFIG_TPL_SERIAL_SUPPORT) += drivers/serial/libserial.o
+LIBS-$(CONFIG_TPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/libspi_flash.o
+LIBS-$(CONFIG_TPL_SPI_SUPPORT) += drivers/spi/libspi.o
+LIBS-$(CONFIG_TPL_FAT_SUPPORT) += fs/fat/libfat.o
+LIBS-$(CONFIG_TPL_LIBGENERIC_SUPPORT) += lib/libgeneric.o
+LIBS-$(CONFIG_TPL_POWER_SUPPORT) += drivers/power/libpower.o
+LIBS-$(CONFIG_TPL_NAND_SUPPORT) += drivers/mtd/nand/libnand.o
+LIBS-$(CONFIG_TPL_ONENAND_SUPPORT) += drivers/mtd/onenand/libonenand.o
+LIBS-$(CONFIG_TPL_DMA_SUPPORT) += drivers/dma/libdma.o
+LIBS-$(CONFIG_TPL_POST_MEM_SUPPORT) += post/drivers/memory.o
+LIBS-$(CONFIG_TPL_NET_SUPPORT) += net/libnet.o
+LIBS-$(CONFIG_TPL_ETH_SUPPORT) += drivers/net/libnet.o
+LIBS-$(CONFIG_TPL_ETH_SUPPORT) += drivers/net/phy/libphy.o
+LIBS-$(CONFIG_TPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/libusb_musb-new.o
+LIBS-$(CONFIG_TPL_USBETH_SUPPORT) += drivers/usb/gadget/libusb_gadget.o
+
+# Add GCC lib
+ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
+PLATFORM_LIBGCC = $(TPLTREE)/arch/$(ARCH)/lib/libgcc.o
+PLATFORM_LIBS := $(filter-out %/libgcc.o, $(filter-out -lgcc, $(PLATFORM_LIBS))) $(PLATFORM_LIBGCC)
+endif
+
+START := $(addprefix $(TPLTREE)/,$(START))
+LIBS := $(addprefix $(TPLTREE)/,$(sort $(LIBS-y)))
+
+__START := $(subst $(obj),,$(START))
+__LIBS := $(subst $(obj),,$(LIBS))
+
+# Linker Script
+ifdef CONFIG_TPL_LDSCRIPT
+# need to strip off double quotes
+LDSCRIPT := $(addprefix $(SRCTREE)/,$(subst ",,$(CONFIG_TPL_LDSCRIPT)))
+endif
+
+ifeq ($(wildcard $(LDSCRIPT)),)
+	LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-tpl.lds
+endif
+ifeq ($(wildcard $(LDSCRIPT)),)
+	LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-tpl.lds
+endif
+ifeq ($(wildcard $(LDSCRIPT)),)
+	LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot-tpl.lds
+endif
+ifeq ($(wildcard $(LDSCRIPT)),)
+$(error could not find linker script)
+endif
+
+# Special flags for CPP when processing the linker script.
+# Pass the version down so we can handle backwards compatibility
+# on the fly.
+LDPPFLAGS += \
+	-include $(TOPDIR)/include/u-boot/u-boot.lds.h \
+	-include $(OBJTREE)/include/config.h \
+	-DCPUDIR=$(CPUDIR) \
+	$(shell $(LD) --version | \
+	  sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p')
+
+$(OBJTREE)/MLO:	$(obj)u-boot-tpl.bin
+	$(OBJTREE)/tools/mkimage -T omapimage \
+		-a $(CONFIG_TPL_TEXT_BASE) -d $< $@
+
+$(OBJTREE)/MLO.byteswap: $(obj)u-boot-tpl.bin
+	$(OBJTREE)/tools/mkimage -T omapimage -n byteswap \
+		-a $(CONFIG_TPL_TEXT_BASE) -d $< $@
+
+$(OBJTREE)/TPL : $(obj)u-boot-tpl.bin depend
+		$(MAKE) -C $(SRCTREE)/arch/arm/imx-common $@
+
+ALL-y	+= $(obj)u-boot-tpl.bin
+
+all:	$(ALL-y)
+
+$(obj)u-boot-tpl.bin:	$(obj)u-boot-tpl
+	$(OBJCOPY) $(OBJCFLAGS) -O binary $< $@
+
+GEN_UBOOT = \
+	cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $(__START) \
+		--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
+		-Map u-boot-tpl.map -o u-boot-tpl
+
+$(obj)u-boot-tpl:	depend $(START) $(LIBS) $(obj)u-boot-tpl.lds
+	$(GEN_UBOOT)
+
+$(START):	depend
+	$(MAKE) -C $(SRCTREE)/$(START_PATH) $@
+
+$(LIBS):	depend
+	$(MAKE) -C $(SRCTREE)$(dir $(subst $(TPLTREE),,$@))
+
+$(obj)u-boot-tpl.lds: $(LDSCRIPT) depend
+	$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj). -ansi -D__ASSEMBLY__ -P - < $< > $@
+
+depend:	$(obj).depend
+.PHONY: depend
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
-- 
1.7.0.4




More information about the U-Boot mailing list