Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
diff --git a/.checkpatch.conf b/.checkpatch.conf
index d88af57..35167e1 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -18,3 +18,6 @@
 
 # Not Linux, so we don't recommend usleep_range() over udelay()
 --ignore USLEEP_RANGE
+
+# Ignore networking block comment style
+--ignore NETWORKING_BLOCK_COMMENT_STYLE
diff --git a/Makefile b/Makefile
index 693b3f2..ba1c10b 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@
 VERSION = 2013
 PATCHLEVEL = 07
 SUBLEVEL =
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 ifneq "$(SUBLEVEL)" ""
 U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 else
@@ -247,6 +247,7 @@
 HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
 
 LIBS-y += lib/libgeneric.o
+LIBS-y += lib/rsa/librsa.o
 LIBS-y += lib/lzma/liblzma.o
 LIBS-y += lib/lzo/liblzo.o
 LIBS-y += lib/zlib/libz.o
@@ -743,6 +744,13 @@
 	$(MAKE) -C $@ all
 endif	# config.mk
 
+# ARM relocations should all be R_ARM_RELATIVE.
+checkarmreloc: $(obj)u-boot
+	@if test "R_ARM_RELATIVE" != \
+		"`readelf -r $< | cut -d ' ' -f 4 | grep R_ARM | sort -u`"; \
+		then echo "$< contains relocations other than \
+		R_ARM_RELATIVE"; false; fi
+
 $(VERSION_FILE):
 		@mkdir -p $(dir $(VERSION_FILE))
 		@( localvers='$(shell $(TOPDIR)/tools/setlocalversion $(TOPDIR))' ; \
@@ -824,7 +832,8 @@
 	       $(obj)tools/mk{smdk5250,}spl				  \
 	       $(obj)tools/mxsboot					  \
 	       $(obj)tools/ncb		   $(obj)tools/ubsha1		  \
-	       $(obj)tools/kernel-doc/docproc
+	       $(obj)tools/kernel-doc/docproc				  \
+	       $(obj)tools/proftool
 	@rm -f $(obj)board/cray/L1/{bootscript.c,bootscript.image}	  \
 	       $(obj)board/matrix_vision/*/bootscript.img		  \
 	       $(obj)board/voiceblue/eeprom 				  \
diff --git a/README b/README
index cd0336c..5c343da 100644
--- a/README
+++ b/README
@@ -413,11 +413,22 @@
 		See Freescale App Note 4493 for more information about
 		this erratum.
 
+		CONFIG_A003399_NOR_WORKAROUND
+		Enables a workaround for IFC erratum A003399. It is only
+		requred during NOR boot.
+
 		CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
 
 		This is the value to write into CCSR offset 0x18600
 		according to the A004510 workaround.
 
+		CONFIG_SYS_FSL_DSP_M2_RAM_ADDR
+		This value denotes start offset of M2 memory
+		which is directly connected to the DSP core.
+
+		CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
+		This value denotes start offset of DSP CCSR space.
+
 - Generic CPU options:
 		CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN
 
@@ -843,7 +854,7 @@
 		CONFIG_CMD_FDOS		* Dos diskette Support
 		CONFIG_CMD_FLASH	  flinfo, erase, protect
 		CONFIG_CMD_FPGA		  FPGA device initialization support
-		CONFIG_CMD_FUSE		  Device fuse support
+		CONFIG_CMD_FUSE		* Device fuse support
 		CONFIG_CMD_GETTIME	* Get time since boot
 		CONFIG_CMD_GO		* the 'go' command (exec code)
 		CONFIG_CMD_GREPENV	* search environment
@@ -853,7 +864,7 @@
 		CONFIG_CMD_IDE		* IDE harddisk support
 		CONFIG_CMD_IMI		  iminfo
 		CONFIG_CMD_IMLS		  List all images found in NOR flash
-		CONFIG_CMD_IMLS_NAND	  List all images found in NAND flash
+		CONFIG_CMD_IMLS_NAND	* List all images found in NAND flash
 		CONFIG_CMD_IMMAP	* IMMR dump support
 		CONFIG_CMD_IMPORTENV	* import an environment
 		CONFIG_CMD_INI		* import data from an ini file into the env
@@ -861,23 +872,24 @@
 		CONFIG_CMD_ITEST	  Integer/string test of 2 values
 		CONFIG_CMD_JFFS2	* JFFS2 Support
 		CONFIG_CMD_KGDB		* kgdb
-		CONFIG_CMD_LDRINFO	  ldrinfo (display Blackfin loader)
+		CONFIG_CMD_LDRINFO	* ldrinfo (display Blackfin loader)
 		CONFIG_CMD_LINK_LOCAL	* link-local IP address auto-configuration
 					  (169.254.*.*)
 		CONFIG_CMD_LOADB	  loadb
 		CONFIG_CMD_LOADS	  loads
-		CONFIG_CMD_MD5SUM	  print md5 message digest
+		CONFIG_CMD_MD5SUM	* print md5 message digest
 					  (requires CONFIG_CMD_MEMORY and CONFIG_MD5)
 		CONFIG_CMD_MEMINFO	* Display detailed memory information
 		CONFIG_CMD_MEMORY	  md, mm, nm, mw, cp, cmp, crc, base,
 					  loop, loopw
-		CONFIG_CMD_MEMTEST	  mtest
+		CONFIG_CMD_MEMTEST	* mtest
 		CONFIG_CMD_MISC		  Misc functions like sleep etc
 		CONFIG_CMD_MMC		* MMC memory mapped support
 		CONFIG_CMD_MII		* MII utility commands
 		CONFIG_CMD_MTDPARTS	* MTD partition support
 		CONFIG_CMD_NAND		* NAND support
 		CONFIG_CMD_NET		  bootp, tftpboot, rarpboot
+		CONFIG_CMD_NFS		  NFS support
 		CONFIG_CMD_PCA953X	* PCA953x I2C gpio commands
 		CONFIG_CMD_PCA953X_INFO * PCA953x I2C gpio info command
 		CONFIG_CMD_PCI		* pciinfo
@@ -896,7 +908,7 @@
 		CONFIG_CMD_SETGETDCR	  Support for DCR Register access
 					  (4xx only)
 		CONFIG_CMD_SF		* Read/write/erase SPI NOR flash
-		CONFIG_CMD_SHA1SUM	  print sha1 memory digest
+		CONFIG_CMD_SHA1SUM	* print sha1 memory digest
 					  (requires CONFIG_CMD_MEMORY)
 		CONFIG_CMD_SOFTSWITCH	* Soft switch setting command for BF60x
 		CONFIG_CMD_SOURCE	  "source" command Support
@@ -908,6 +920,7 @@
 		CONFIG_CMD_USB		* USB support
 		CONFIG_CMD_CDP		* Cisco Discover Protocol support
 		CONFIG_CMD_MFSL		* Microblaze FSL support
+		CONFIG_CMD_XIMG		  Load part of Multi Image
 
 
 		EXAMPLE: If you want all functions except of network
@@ -1432,6 +1445,11 @@
 		Export function i8042_kbd_init, i8042_tstc and i8042_getc
 		for cfb_console. Supports cursor blinking.
 
+		CONFIG_CROS_EC_KEYB
+		Enables a Chrome OS keyboard using the CROS_EC interface.
+		This uses CROS_EC to communicate with a second microcontroller
+		which provides key scans on request.
+
 - Video support:
 		CONFIG_VIDEO
 
@@ -2509,6 +2527,11 @@
 		Define this option to include a destructive SPI flash
 		test ('sf test').
 
+		CONFIG_SPI_FLASH_BAR		Ban/Extended Addr Reg
+
+		Define this option to use the Bank addr/Extended addr
+		support on SPI flashes which has size > 16Mbytes.
+
 - SystemACE Support:
 		CONFIG_SYSTEMACE
 
@@ -2560,6 +2583,16 @@
 		Note: There is also a sha1sum command, which should perhaps
 		be deprecated in favour of 'hash sha1'.
 
+- Signing support:
+		CONFIG_RSA
+
+		This enables the RSA algorithm used for FIT image verification
+		in U-Boot. See doc/uImage/signature for more information.
+
+		The signing part is build into mkimage regardless of this
+		option.
+
+
 - Show boot progress:
 		CONFIG_SHOW_BOOT_PROGRESS
 
@@ -2784,6 +2817,11 @@
 		most specific compatibility entry of U-Boot's fdt's root node.
 		The order of entries in the configuration's fdt is ignored.
 
+		CONFIG_FIT_SIGNATURE
+		This option enables signature verification of FIT uImages,
+		using a hash signed and verified using RSA. See
+		doc/uImage.FIT/signature.txt for more details.
+
 - Standalone program support:
 		CONFIG_STANDALONE_LOAD_ADDR
 
@@ -3022,6 +3060,14 @@
 		CONFIG_SPL_LIBGENERIC_SUPPORT
 		Support for lib/libgeneric.o in SPL binary
 
+		CONFIG_SPL_ENV_SUPPORT
+		Support for the environment operating in SPL binary
+
+		CONFIG_SPL_NET_SUPPORT
+		Support for the net/libnet.o in SPL binary.
+		It conflicts with SPL env from storage medium specified by
+		CONFIG_ENV_IS_xxx but CONFIG_ENV_IS_NOWHERE
+
 		CONFIG_SPL_PAD_TO
 		Image offset to which the SPL should be padded before appending
 		the SPL payload. By default, this is defined as
@@ -3964,6 +4010,9 @@
 - CONFIG_SRIO2:
 		Board has SRIO 2 port available
 
+- CONFIG_SRIO_PCIE_BOOT_MASTER
+		Board can support master function for Boot from SRIO and PCIE
+
 - CONFIG_SYS_SRIOn_MEM_VIRT:
 		Virtual Address of SRIO port 'n' memory region
 
@@ -4074,6 +4123,11 @@
 		that is executed before the actual U-Boot. E.g. when
 		compiling a NAND SPL.
 
+- CONFIG_SYS_MPC85XX_NO_RESETVEC
+		Only for 85xx systems. If this variable is specified, the section
+		.resetvec is not kept and the section .bootpg is placed in the
+		previous 4k of the .text section.
+
 - CONFIG_ARCH_MAP_SYSMEM
 		Generally U-Boot (and in particular the md command) uses
 		effective address. It is therefore not necessary to regard
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index dc64160..e80e1ed 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -109,3 +109,8 @@
 PLATFORM_RELFLAGS += -fno-optimize-sibling-calls
 endif
 endif
+
+# check that only R_ARM_RELATIVE relocations are generated
+ifneq ($(CONFIG_SPL_BUILD),y)
+ALL-y	+= checkarmreloc
+endif
diff --git a/arch/arm/cpu/arm920t/ep93xx/u-boot.lds b/arch/arm/cpu/arm920t/ep93xx/u-boot.lds
index cf55bf7..367c805 100644
--- a/arch/arm/cpu/arm920t/ep93xx/u-boot.lds
+++ b/arch/arm/cpu/arm920t/ep93xx/u-boot.lds
@@ -31,6 +31,7 @@
 	. = ALIGN(4);
 	.text      :
 	{
+		*(.__image_copy_start)
 	  arch/arm/cpu/arm920t/start.o	(.text*)
 		/* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */
 	  . = 0x1000;
@@ -56,7 +57,10 @@
 
 	. = ALIGN(4);
 
-	__image_copy_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
+	}
 
 	__bss_start = .;
 	.bss : { *(.bss*) }
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
index 673c725..f4e7525 100644
--- a/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
+++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
@@ -57,11 +57,6 @@
 		__rel_dyn_end = .;
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	}
-
 	.bss : {
 		. = ALIGN(4);
 		__bss_start = .;
diff --git a/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
index 967a135..446d095 100644
--- a/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
+++ b/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
@@ -57,11 +57,6 @@
 		__rel_dyn_end = .;
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	}
-
 	.bss : {
 		. = ALIGN(4);
 		__bss_start = .;
diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c
index 885fb2d..b935a29 100644
--- a/arch/arm/cpu/armv7/am33xx/board.c
+++ b/arch/arm/cpu/armv7/am33xx/board.c
@@ -149,3 +149,43 @@
 #endif
 	return 0;
 }
+
+#ifdef CONFIG_SPL_BUILD
+void rtc32k_enable(void)
+{
+	struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
+
+	/*
+	 * Unlock the RTC's registers.  For more details please see the
+	 * RTC_SS section of the TRM.  In order to unlock we need to
+	 * write these specific values (keys) in this order.
+	 */
+	writel(0x83e70b13, &rtc->kick0r);
+	writel(0x95a4f1e0, &rtc->kick1r);
+
+	/* Enable the RTC 32K OSC by setting bits 3 and 6. */
+	writel((1 << 3) | (1 << 6), &rtc->osc);
+}
+
+#define UART_RESET		(0x1 << 1)
+#define UART_CLK_RUNNING_MASK	0x1
+#define UART_SMART_IDLE_EN	(0x1 << 0x3)
+
+void uart_soft_reset(void)
+{
+	struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
+	u32 regval;
+
+	regval = readl(&uart_base->uartsyscfg);
+	regval |= UART_RESET;
+	writel(regval, &uart_base->uartsyscfg);
+	while ((readl(&uart_base->uartsyssts) &
+		UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
+		;
+
+	/* Disable smart idle */
+	regval = readl(&uart_base->uartsyscfg);
+	regval |= UART_SMART_IDLE_EN;
+	writel(regval, &uart_base->uartsyscfg);
+}
+#endif
diff --git a/arch/arm/cpu/armv7/am33xx/clock_am33xx.c b/arch/arm/cpu/armv7/am33xx/clock_am33xx.c
index a1efc75..9c4d0b4 100644
--- a/arch/arm/cpu/armv7/am33xx/clock_am33xx.c
+++ b/arch/arm/cpu/armv7/am33xx/clock_am33xx.c
@@ -246,7 +246,7 @@
 		;
 }
 
-static void mpu_pll_config(void)
+void mpu_pll_config_val(int mpull_m)
 {
 	u32 clkmode, clksel, div_m2;
 
@@ -260,7 +260,7 @@
 		;
 
 	clksel = clksel & (~CLK_SEL_MASK);
-	clksel = clksel | ((MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N);
+	clksel = clksel | ((mpull_m << CLK_SEL_SHIFT) | MPUPLL_N);
 	writel(clksel, &cmwkup->clkseldpllmpu);
 
 	div_m2 = div_m2 & ~CLK_DIV_MASK;
@@ -274,6 +274,11 @@
 		;
 }
 
+static void mpu_pll_config(void)
+{
+	mpu_pll_config_val(CONFIG_SYS_MPUCLK);
+}
+
 static void core_pll_config(void)
 {
 	u32 clkmode, clksel, div_m4, div_m5, div_m6;
diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile
index 9119961..b2f9152 100644
--- a/arch/arm/cpu/armv7/exynos/Makefile
+++ b/arch/arm/cpu/armv7/exynos/Makefile
@@ -22,7 +22,7 @@
 
 LIB	= $(obj)lib$(SOC).o
 
-COBJS	+= clock.o power.o soc.o system.o pinmux.o
+COBJS	+= clock.o power.o soc.o system.o pinmux.o tzpc.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 223660a..e1c4246 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -116,10 +116,8 @@
 		/* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
 		fout = (m + k / 1024) * (freq / (p * (1 << s)));
 	} else {
-		if (s < 1)
-			s = 1;
-		/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
-		fout = m * (freq / (p * (1 << (s - 1))));
+		/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
+		fout = m * (freq / (p * (1 << s)));
 	}
 
 	return fout;
@@ -613,7 +611,7 @@
 		(struct exynos4_clock *)samsung_get_base_clock();
 	unsigned long uclk, sclk;
 	unsigned int sel, ratio, pre_ratio;
-	int shift;
+	int shift = 0;
 
 	sel = readl(&clk->src_fsys);
 	sel = (sel >> (dev_index << 2)) & 0xf;
@@ -662,7 +660,7 @@
 		(struct exynos5_clock *)samsung_get_base_clock();
 	unsigned long uclk, sclk;
 	unsigned int sel, ratio, pre_ratio;
-	int shift;
+	int shift = 0;
 
 	sel = readl(&clk->src_fsys);
 	sel = (sel >> (dev_index << 2)) & 0xf;
diff --git a/board/samsung/smdk5250/tzpc_init.c b/arch/arm/cpu/armv7/exynos/tzpc.c
similarity index 69%
rename from board/samsung/smdk5250/tzpc_init.c
rename to arch/arm/cpu/armv7/exynos/tzpc.c
index c833541..f5e8e9c 100644
--- a/board/samsung/smdk5250/tzpc_init.c
+++ b/arch/arm/cpu/armv7/exynos/tzpc.c
@@ -22,27 +22,36 @@
  * MA 02111-1307 USA
  */
 
+#include <common.h>
 #include <asm/arch/tzpc.h>
-#include"setup.h"
+#include <asm/io.h>
 
 /* Setting TZPC[TrustZone Protection Controller] */
 void tzpc_init(void)
 {
 	struct exynos_tzpc *tzpc;
-	unsigned int addr;
+	unsigned int addr, start = 0, end = 0;
 
-	for (addr = TZPC0_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) {
+	start = samsung_get_base_tzpc();
+
+	if (cpu_is_exynos5())
+		end = start + ((EXYNOS5_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET);
+	else if (cpu_is_exynos4())
+		end = start + ((EXYNOS4_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET);
+
+	for (addr = start; addr <= end; addr += TZPC_BASE_OFFSET) {
 		tzpc = (struct exynos_tzpc *)addr;
 
-		if (addr == TZPC0_BASE)
+		if (addr == start)
 			writel(R0SIZE, &tzpc->r0size);
 
 		writel(DECPROTXSET, &tzpc->decprot0set);
 		writel(DECPROTXSET, &tzpc->decprot1set);
 
-		if (addr != TZPC9_BASE) {
-			writel(DECPROTXSET, &tzpc->decprot2set);
-			writel(DECPROTXSET, &tzpc->decprot3set);
-		}
+		if (cpu_is_exynos5() && (addr == end))
+			break;
+
+		writel(DECPROTXSET, &tzpc->decprot2set);
+		writel(DECPROTXSET, &tzpc->decprot3set);
 	}
 }
diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile
index 1705399..0c38bd0 100644
--- a/arch/arm/cpu/armv7/s5p-common/Makefile
+++ b/arch/arm/cpu/armv7/s5p-common/Makefile
@@ -26,9 +26,11 @@
 LIB	= $(obj)libs5p-common.o
 
 COBJS-y		+= cpu_info.o
+ifndef CONFIG_SPL_BUILD
 COBJS-y		+= timer.o
 COBJS-y		+= sromc.o
 COBJS-$(CONFIG_PWM)	+= pwm.o
+endif
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c
index 4adfaae..637593c 100644
--- a/arch/arm/cpu/armv7/s5p-common/timer.c
+++ b/arch/arm/cpu/armv7/s5p-common/timer.c
@@ -95,7 +95,7 @@
 	return time_ms - base;
 }
 
-unsigned long timer_get_us(void)
+unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
 {
 	static unsigned long base_time_us;
 
diff --git a/arch/arm/cpu/ixp/u-boot.lds b/arch/arm/cpu/ixp/u-boot.lds
index 553589c..54bafda 100644
--- a/arch/arm/cpu/ixp/u-boot.lds
+++ b/arch/arm/cpu/ixp/u-boot.lds
@@ -31,6 +31,7 @@
 	. = ALIGN(4);
 	.text :
 	{
+		*(.__image_copy_start)
 		arch/arm/cpu/ixp/start.o(.text*)
 		*(.text*)
 	}
@@ -54,17 +55,23 @@
 
 	. = ALIGN(4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -88,6 +95,7 @@
 		KEEP(*(.__bss_end));
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/arch/arm/cpu/u-boot-spl.lds b/arch/arm/cpu/u-boot-spl.lds
index 1408f03..b6ed25f 100644
--- a/arch/arm/cpu/u-boot-spl.lds
+++ b/arch/arm/cpu/u-boot-spl.lds
@@ -58,11 +58,6 @@
 		__rel_dyn_end = .;
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	}
-
 	_end = .;
 
 	.bss __rel_dyn_start (OVERLAY) : {
@@ -72,6 +67,7 @@
 		__bss_end = .;
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index d9bbee3..3037885 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -33,7 +33,7 @@
 	. = ALIGN(4);
 	.text :
 	{
-		__image_copy_start = .;
+		*(.__image_copy_start)
 		CPUDIR/start.o (.text*)
 		*(.text*)
 	}
@@ -57,17 +57,23 @@
 
 	. = ALIGN(4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -101,6 +107,7 @@
 		KEEP(*(.__bss_end));
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi
index df4b231..2d6dfff 100644
--- a/arch/arm/dts/exynos5250.dtsi
+++ b/arch/arm/dts/exynos5250.dtsi
@@ -169,4 +169,39 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 	};
+
+	mmc@12200000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12200000 0x1000>;
+		interrupts = <0 75 0>;
+	};
+
+	mmc@12210000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12210000 0x1000>;
+		interrupts = <0 76 0>;
+	};
+
+	mmc@12220000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12220000 0x1000>;
+		interrupts = <0 77 0>;
+	};
+
+	mmc@12230000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12230000 0x1000>;
+		interrupts = <0 78 0>;
+	};
+
+	gpio: gpio {
+	};
 };
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index fedc674..307ac28 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -32,6 +32,7 @@
 u32 get_device_type(void);
 void save_omap_boot_params(void);
 void setup_clocks_for_console(void);
+void mpu_pll_config_val(int mpull_m);
 void ddr_pll_config(unsigned int ddrpll_M);
 
 void sdelay(unsigned long);
@@ -41,4 +42,7 @@
 void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
 			u32 size);
 void omap_nand_switch_ecc(uint32_t, uint32_t);
+
+void rtc32k_enable(void);
+void uart_soft_reset(void);
 #endif
diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
index f76e489..1ff7642 100644
--- a/arch/arm/include/asm/arch-exynos/cpu.h
+++ b/arch/arm/include/asm/arch-exynos/cpu.h
@@ -38,6 +38,7 @@
 #define EXYNOS4_CLOCK_BASE		0x10030000
 #define EXYNOS4_SYSTIMER_BASE		0x10050000
 #define EXYNOS4_WATCHDOG_BASE		0x10060000
+#define EXYNOS4_TZPC_BASE		0x10110000
 #define EXYNOS4_MIU_BASE		0x10600000
 #define EXYNOS4_DMC0_BASE		0x10400000
 #define EXYNOS4_DMC1_BASE		0x10410000
@@ -74,6 +75,7 @@
 #define EXYNOS4X12_CLOCK_BASE		0x10030000
 #define EXYNOS4X12_SYSTIMER_BASE	0x10050000
 #define EXYNOS4X12_WATCHDOG_BASE	0x10060000
+#define EXYNOS4X12_TZPC_BASE		0x10110000
 #define EXYNOS4X12_DMC0_BASE		0x10600000
 #define EXYNOS4X12_DMC1_BASE		0x10610000
 #define EXYNOS4X12_GPIO_PART4_BASE	0x106E0000
@@ -107,6 +109,7 @@
 #define EXYNOS5_POWER_BASE		0x10040000
 #define EXYNOS5_SWRESET			0x10040400
 #define EXYNOS5_SYSREG_BASE		0x10050000
+#define EXYNOS5_TZPC_BASE		0x10100000
 #define EXYNOS5_WATCHDOG_BASE		0x101D0000
 #define EXYNOS5_ACE_SFR_BASE            0x10830000
 #define EXYNOS5_DMC_PHY0_BASE		0x10C00000
@@ -175,7 +178,7 @@
 }
 
 #define IS_SAMSUNG_TYPE(type, id)			\
-static inline int cpu_is_##type(void)			\
+static inline int __attribute__((no_instrument_function)) cpu_is_##type(void) \
 {							\
 	return (s5p_cpu_id >> 12) == id;		\
 }
@@ -184,7 +187,8 @@
 IS_SAMSUNG_TYPE(exynos5, 0x5)
 
 #define IS_EXYNOS_TYPE(type, id)			\
-static inline int proid_is_##type(void)			\
+static inline int __attribute__((no_instrument_function)) \
+	proid_is_##type(void)				\
 {							\
 	return s5p_cpu_id == id;			\
 }
@@ -194,9 +198,10 @@
 IS_EXYNOS_TYPE(exynos5250, 0x5250)
 
 #define SAMSUNG_BASE(device, base)				\
-static inline unsigned int samsung_get_base_##device(void)	\
+static inline unsigned int __attribute__((no_instrument_function)) \
+	samsung_get_base_##device(void) \
 {								\
-	if (cpu_is_exynos4()) {					\
+	if (cpu_is_exynos4()) {				\
 		if (proid_is_exynos4412())			\
 			return EXYNOS4X12_##base;		\
 		return EXYNOS4_##base;				\
@@ -233,6 +238,7 @@
 SAMSUNG_BASE(power, POWER_BASE)
 SAMSUNG_BASE(spi, SPI_BASE)
 SAMSUNG_BASE(spi_isp, SPI_ISP_BASE)
+SAMSUNG_BASE(tzpc, TZPC_BASE)
 #endif
 
 #endif	/* _EXYNOS4_CPU_H */
diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h
index 8acdf9b..3b147b8 100644
--- a/arch/arm/include/asm/arch-exynos/dwmmc.h
+++ b/arch/arm/include/asm/arch-exynos/dwmmc.h
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x)	((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);
-
-static inline unsigned int exynos_dwmmc_init(int index, int bus_width)
-{
-	unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
-	return exynos_dwmci_init(base, bus_width, index);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel);
diff --git a/arch/arm/include/asm/arch-exynos/tmu.h b/arch/arm/include/asm/arch-exynos/tmu.h
index 7e0158e..cad3569 100644
--- a/arch/arm/include/asm/arch-exynos/tmu.h
+++ b/arch/arm/include/asm/arch-exynos/tmu.h
@@ -21,38 +21,30 @@
 #define __ASM_ARCH_TMU_H
 
 struct exynos5_tmu_reg {
-	unsigned triminfo;
-	unsigned rsvd1;
-	unsigned rsvd2;
-	unsigned rsvd3;
-	unsigned rsvd4;
-	unsigned triminfo_control;
-	unsigned rsvd5;
-	unsigned rsvd6;
-	unsigned tmu_control;
-	unsigned rsvd7;
-	unsigned tmu_status;
-	unsigned sampling_internal;
-	unsigned counter_value0;
-	unsigned counter_value1;
-	unsigned rsvd8;
-	unsigned rsvd9;
-	unsigned current_temp;
-	unsigned rsvd10;
-	unsigned rsvd11;
-	unsigned rsvd12;
-	unsigned threshold_temp_rise;
-	unsigned threshold_temp_fall;
-	unsigned rsvd13;
-	unsigned rsvd14;
-	unsigned past_temp3_0;
-	unsigned past_temp7_4;
-	unsigned past_temp11_8;
-	unsigned past_temp15_12;
-	unsigned inten;
-	unsigned intstat;
-	unsigned intclear;
-	unsigned rsvd15;
-	unsigned emul_con;
+	u32 triminfo;
+	u32 rsvd1[4];
+	u32 triminfo_control;
+	u32 rsvd5[2];
+	u32 tmu_control;
+	u32 rsvd7;
+	u32 tmu_status;
+	u32 sampling_internal;
+	u32 counter_value0;
+	u32 counter_value1;
+	u32 rsvd8[2];
+	u32 current_temp;
+	u32 rsvd10[3];
+	u32 threshold_temp_rise;
+	u32 threshold_temp_fall;
+	u32 rsvd13[2];
+	u32 past_temp3_0;
+	u32 past_temp7_4;
+	u32 past_temp11_8;
+	u32 past_temp15_12;
+	u32 inten;
+	u32 intstat;
+	u32 intclear;
+	u32 rsvd15;
+	u32 emul_con;
 };
 #endif /* __ASM_ARCH_TMU_H */
diff --git a/arch/arm/include/asm/arch-exynos/tzpc.h b/arch/arm/include/asm/arch-exynos/tzpc.h
index c5eb4b1..4d9c3a3 100644
--- a/arch/arm/include/asm/arch-exynos/tzpc.h
+++ b/arch/arm/include/asm/arch-exynos/tzpc.h
@@ -47,6 +47,26 @@
 	unsigned int pcellid2;
 	unsigned int pcellid3;
 };
+
+#define EXYNOS4_NR_TZPC_BANKS		6
+#define EXYNOS5_NR_TZPC_BANKS		10
+
+/* TZPC : Register Offsets */
+#define TZPC_BASE_OFFSET		0x10000
+
+/*
+ * TZPC Register Value :
+ * R0SIZE: 0x0 : Size of secured ram
+ */
+#define R0SIZE			0x0
+
+/*
+ * TZPC Decode Protection Register Value :
+ * DECPROTXSET: 0xFF : Set Decode region to non-secure
+ */
+#define DECPROTXSET		0xFF
+void tzpc_init(void);
+
 #endif
 
 #endif
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 8ad9f66..9ecafb2 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -43,7 +43,7 @@
 ifndef CONFIG_SYS_GENERIC_BOARD
 COBJS-y	+= board.o
 endif
-COBJS-y += bss.o
+COBJS-y += sections.o
 
 COBJS-y	+= bootm.o
 COBJS-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 1b6e0ac..b22fbc9 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -68,12 +68,19 @@
 		    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
 }
 
-static void announce_and_cleanup(void)
+/**
+ * announce_and_cleanup() - Print message and prepare for kernel boot
+ *
+ * @fake: non-zero to do everything except actually boot
+ */
+static void announce_and_cleanup(int fake)
 {
-	printf("\nStarting kernel ...\n\n");
+	printf("\nStarting kernel ...%s\n\n", fake ?
+		"(fake run for tracing)" : "");
 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
 #ifdef CONFIG_BOOTSTAGE_FDT
-	bootstage_fdt_add_report();
+	if (flag == BOOTM_STATE_OS_FAKE_GO)
+		bootstage_fdt_add_report();
 #endif
 #ifdef CONFIG_BOOTSTAGE_REPORT
 	bootstage_report();
@@ -225,12 +232,13 @@
 }
 
 /* Subcommand: GO */
-static void boot_jump_linux(bootm_headers_t *images)
+static void boot_jump_linux(bootm_headers_t *images, int flag)
 {
 	unsigned long machid = gd->bd->bi_arch_number;
 	char *s;
 	void (*kernel_entry)(int zero, int arch, uint params);
 	unsigned long r2;
+	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
 
 	kernel_entry = (void (*)(int, int, uint))images->ep;
 
@@ -243,14 +251,15 @@
 	debug("## Transferring control to Linux (at address %08lx)" \
 		"...\n", (ulong) kernel_entry);
 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
-	announce_and_cleanup();
+	announce_and_cleanup(fake);
 
 	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
 		r2 = (unsigned long)images->ft_addr;
 	else
 		r2 = gd->bd->bi_boot_params;
 
-	kernel_entry(0, machid, r2);
+	if (!fake)
+		kernel_entry(0, machid, r2);
 }
 
 /* Main Entry point for arm bootm implementation
@@ -270,13 +279,13 @@
 		return 0;
 	}
 
-	if (flag & BOOTM_STATE_OS_GO) {
-		boot_jump_linux(images);
+	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+		boot_jump_linux(images, flag);
 		return 0;
 	}
 
 	boot_prep_linux(images);
-	boot_jump_linux(images);
+	boot_jump_linux(images, flag);
 	return 0;
 }
 
diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S
index 4446da9..949b9e8 100644
--- a/arch/arm/lib/relocate.S
+++ b/arch/arm/lib/relocate.S
@@ -37,56 +37,34 @@
  */
 
 ENTRY(relocate_code)
-	mov	r6, r0	/* save addr of destination */
-
-	ldr	r0, =_start		/* r0 <- SRC &_start */
-	subs	r9, r6, r0		/* r9 <- relocation offset */
+	ldr	r1, =__image_copy_start	/* r1 <- SRC &__image_copy_start */
+	subs	r9, r0, r1		/* r9 <- relocation offset */
 	beq	relocate_done		/* skip relocation */
-	mov	r1, r6			/* r1 <- scratch for copy loop */
-	adr	r7, relocate_code	/* r7 <- SRC &relocate_code */
-	ldr	r3, _image_copy_end_ofs	/* r3 <- __image_copy_end local ofs */
-	add	r2, r7, r3		/* r2 <- SRC &__image_copy_end */
+	ldr	r2, =__image_copy_end	/* r2 <- SRC &__image_copy_end */
 
 copy_loop:
-	ldmia	r0!, {r10-r11}		/* copy from source address [r0]    */
-	stmia	r1!, {r10-r11}		/* copy to   target address [r1]    */
-	cmp	r0, r2			/* until source end address [r2]    */
+	ldmia	r1!, {r10-r11}		/* copy from source address [r1]    */
+	stmia	r0!, {r10-r11}		/* copy to   target address [r0]    */
+	cmp	r1, r2			/* until source end address [r2]    */
 	blo	copy_loop
 
 	/*
 	 * fix .rel.dyn relocations
 	 */
-	ldr	r10, _dynsym_start_ofs	/* r10 <- __dynsym_start local ofs */
-	add	r10, r10, r7		/* r10 <- SRC &__dynsym_start */
-	ldr	r2, _rel_dyn_start_ofs	/* r2 <- __rel_dyn_start local ofs */
-	add	r2, r2, r7		/* r2 <- SRC &__rel_dyn_start */
-	ldr	r3, _rel_dyn_end_ofs	/* r3 <- __rel_dyn_end local ofs */
-	add	r3, r3, r7		/* r3 <- SRC &__rel_dyn_end */
+	ldr	r2, =__rel_dyn_start	/* r2 <- SRC &__rel_dyn_start */
+	ldr	r3, =__rel_dyn_end	/* r3 <- SRC &__rel_dyn_end */
 fixloop:
-	ldr	r0, [r2]		/* r0 <- SRC location to fix up */
-	add	r0, r0, r9		/* r0 <- DST location to fix up */
-	ldr	r1, [r2, #4]
-	and	r7, r1, #0xff
-	cmp	r7, #23			/* relative fixup? */
-	beq	fixrel
-	cmp	r7, #2			/* absolute fixup? */
-	beq	fixabs
-	/* ignore unknown type of fixup */
-	b	fixnext
-fixabs:
-	/* absolute fix: set location to (offset) symbol value */
-	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
-	add	r1, r10, r1		/* r1 <- address of symbol in table */
-	ldr	r1, [r1, #4]		/* r1 <- symbol value */
-	add	r1, r1, r9		/* r1 <- relocated sym addr */
-	b	fixnext
-fixrel:
+	ldmia	r2!, {r0-r1}		/* (r0,r1) <- (SRC location,fixup) */
+	and	r1, r1, #0xff
+	cmp	r1, #23			/* relative fixup? */
+	bne	fixnext
+
 	/* relative fix: increase location by offset */
+	add	r0, r0, r9
 	ldr	r1, [r0]
 	add	r1, r1, r9
-fixnext:
 	str	r1, [r0]
-	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
+fixnext:
 	cmp	r2, r3
 	blo	fixloop
 
@@ -100,13 +78,4 @@
         bx        lr
 #endif
 
-_image_copy_end_ofs:
-	.word __image_copy_end - relocate_code
-_rel_dyn_start_ofs:
-	.word __rel_dyn_start - relocate_code
-_rel_dyn_end_ofs:
-	.word __rel_dyn_end - relocate_code
-_dynsym_start_ofs:
-	.word __dynsym_start - relocate_code
-
 ENDPROC(relocate_code)
diff --git a/arch/arm/lib/bss.c b/arch/arm/lib/sections.c
similarity index 79%
rename from arch/arm/lib/bss.c
rename to arch/arm/lib/sections.c
index 99eda59..5921dd8 100644
--- a/arch/arm/lib/bss.c
+++ b/arch/arm/lib/sections.c
@@ -35,5 +35,9 @@
  * aliasing warnings.
  */
 
-char __bss_start[0] __attribute__((used, section(".__bss_start")));
-char __bss_end[0] __attribute__((used, section(".__bss_end")));
+char __bss_start[0] __attribute__((section(".__bss_start")));
+char __bss_end[0] __attribute__((section(".__bss_end")));
+char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
+char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
+char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
+char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
diff --git a/arch/m68k/cpu/mcf5445x/speed.c b/arch/m68k/cpu/mcf5445x/speed.c
index aa73e1f..0276d4d 100644
--- a/arch/m68k/cpu/mcf5445x/speed.c
+++ b/arch/m68k/cpu/mcf5445x/speed.c
@@ -122,17 +122,17 @@
 
 	vco =  ((in_be32(&pll->pcr) & PLL_CR_FBKDIV_BITS) + 1) *
 		CONFIG_SYS_INPUT_CLKSRC;
-	gd->vco_clk = vco;
+	gd->arch.vco_clk = vco;
 
-	gd->inp_clk = CONFIG_SYS_INPUT_CLKSRC;	/* Input clock */
+	gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC;	/* Input clock */
 
 	pdr = in_be32(&pll->pdr);
 	temp = (pdr & PLL_DR_OUTDIV1_BITS) + 1;
 	gd->cpu_clk = vco / temp;	/* cpu clock */
-	gd->flb_clk = vco / temp;	/* FlexBus clock */
-	gd->flb_clk >>= 1;
+	gd->arch.flb_clk = vco / temp;	/* FlexBus clock */
+	gd->arch.flb_clk >>= 1;
 	if (in_be16(ccm->misccr2) & 2)		/* fsys/4 */
-		gd->flb_clk >>= 1;
+		gd->arch.flb_clk >>= 1;
 
 	temp = ((pdr & PLL_DR_OUTDIV2_BITS) >> 5) + 1;
 	gd->bus_clk = vco / temp;	/* bus clock */
diff --git a/arch/m68k/include/asm/m5235.h b/arch/m68k/include/asm/m5235.h
index 71a40d3..a573f1c 100644
--- a/arch/m68k/include/asm/m5235.h
+++ b/arch/m68k/include/asm/m5235.h
@@ -134,7 +134,7 @@
 #define SDRAMC_DCR_RC(x)		(((x)&0xFF)<<8)
 
 /* Bit definitions and macros for SDRAMC_DARCn */
-#define SDRAMC_DARCn_BA(x)		(((x)&0xFFFC)<<18)
+#define SDRAMC_DARCn_BA(x)		((x)&0xFFFC0000)
 #define SDRAMC_DARCn_RE			(0x00008000)
 #define SDRAMC_DARCn_CASL_MASK		(0x00003000)
 #define SDRAMC_DARCn_CASL_C0		(0x00000000)
diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c
index b2e3068..efc9fcc 100644
--- a/arch/m68k/lib/board.c
+++ b/arch/m68k/lib/board.c
@@ -403,14 +403,14 @@
 
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
 
-	debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
-
 	WATCHDOG_RESET ();
 
 	gd->reloc_off =  dest_addr - CONFIG_SYS_MONITOR_BASE;
 
 	serial_initialize();
 
+	debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
 	monitor_flash_len = (ulong)&__init_end - dest_addr;
 
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c
index 3842709..b328f94 100644
--- a/arch/microblaze/lib/bootm.c
+++ b/arch/microblaze/lib/bootm.c
@@ -62,8 +62,8 @@
 
 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 
-	if (!of_flat_tree && argc > 3)
-		of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
+	if (!of_flat_tree && argc > 1)
+		of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16);
 
 	/* fixup the initrd now that we know where it should be */
 	if (images->rd_start && images->rd_end && of_flat_tree)
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index f32be52..114e146 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -40,8 +40,8 @@
 	if (images->ft_len)
 		of_flat_tree = images->ft_addr;
 #endif
-	if (!of_flat_tree && argc > 3)
-		of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
+	if (!of_flat_tree && argc > 1)
+		of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16);
 	if (of_flat_tree)
 		initrd_end = (ulong)of_flat_tree;
 
diff --git a/arch/openrisc/lib/bootm.c b/arch/openrisc/lib/bootm.c
index 2c5d9ae..7f716b8 100644
--- a/arch/openrisc/lib/bootm.c
+++ b/arch/openrisc/lib/bootm.c
@@ -63,8 +63,8 @@
 
 	show_boot_progress(15);
 
-	if (!of_flat_tree && argc > 3)
-		of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
+	if (!of_flat_tree && argc > 1)
+		of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16);
 #ifdef DEBUG
 	printf("## Transferring control to Linux (at address 0x%08lx) " \
 				"ramdisk 0x%08lx, FDT 0x%08lx...\n",
diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile
index 2318064..4669883 100644
--- a/arch/powerpc/cpu/mpc85xx/Makefile
+++ b/arch/powerpc/cpu/mpc85xx/Makefile
@@ -73,6 +73,7 @@
 COBJS-$(CONFIG_P1020)	+= ddr-gen3.o
 COBJS-$(CONFIG_P1021)	+= ddr-gen3.o
 COBJS-$(CONFIG_P1022)	+= ddr-gen3.o
+COBJS-$(CONFIG_P1023)	+= ddr-gen3.o
 COBJS-$(CONFIG_P1024)	+= ddr-gen3.o
 COBJS-$(CONFIG_P1025)	+= ddr-gen3.o
 COBJS-$(CONFIG_P2010)	+= ddr-gen3.o
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index 422782c..a7ed877 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -258,6 +258,9 @@
 #ifdef CONFIG_SYS_FSL_ERRATUM_USB14
 	puts("Work-around for Erratum USB14 enabled\n");
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006593
+	puts("Work-around for Erratum A006593 enabled\n");
+#endif
 	return 0;
 }
 
diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c
index 6ce483e..fbee753 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu.c
@@ -121,16 +121,16 @@
 	switch(ver) {
 	case PVR_VER_E500_V1:
 	case PVR_VER_E500_V2:
-		puts("E500");
+		puts("e500");
 		break;
 	case PVR_VER_E500MC:
-		puts("E500MC");
+		puts("e500mc");
 		break;
 	case PVR_VER_E5500:
-		puts("E5500");
+		puts("e5500");
 		break;
 	case PVR_VER_E6500:
-		puts("E6500");
+		puts("e6500");
 		break;
 	default:
 		puts("Unknown");
@@ -341,7 +341,7 @@
 #if defined(CONFIG_SPD_EEPROM) || defined(CONFIG_DDR_SPD)
 	return fsl_ddr_sdram_size();
 #else
-	return CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
+	return (phys_size_t)CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
 #endif
 }
 #else /* CONFIG_SYS_RAMBOOT */
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index 4067f05..3c8f59c 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -172,6 +172,9 @@
 #ifdef CONFIG_SYS_FSL_ERRATUM_CPC_A003
 		setbits_be32(&cpc->cpchdbcr0, CPC_HDBCR0_DATA_ECC_SCRUB_DIS);
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006593
+		setbits_be32(&cpc->cpchdbcr0, 1 << (31 - 21));
+#endif
 
 		out_be32(&cpc->cpccsr0, CPC_CSR0_CE | CPC_CSR0_PE);
 		/* Read back to sync write */
@@ -564,7 +567,7 @@
 
 #ifdef CONFIG_SYS_SRIO
 	srio_init();
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER 
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 	char *s = getenv("bootmaster");
 	if (s) {
 		if (!strcmp(s, "SRIO1")) {
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init_early.c b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
index 234fde4..837c034 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
@@ -25,7 +25,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) && !defined(CONFIG_SYS_RAMBOOT)
+#ifdef CONFIG_A003399_NOR_WORKAROUND
 void setup_ifc(void)
 {
 	struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
@@ -99,7 +99,7 @@
 #ifdef CONFIG_SYS_FSL_ERRATUM_P1010_A003549
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 #endif
-#if defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) && !defined(CONFIG_SYS_RAMBOOT)
+#ifdef CONFIG_A003399_NOR_WORKAROUND
 	ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
 	u32  *dst, *src;
 	void (*setup_ifc_sram)(void);
@@ -138,7 +138,7 @@
  * Work Around for IFC Erratum A003399, issue will hit only when execution
  * from NOR Flash
  */
-#if defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) && !defined(CONFIG_SYS_RAMBOOT)
+#ifdef CONFIG_A003399_NOR_WORKAROUND
 #define SRAM_BASE_ADDR	(0x00000000)
 	/* TLB for SRAM */
 	mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(9);
@@ -180,5 +180,9 @@
 
 	invalidate_tlb(1);
 
+#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_NAND_SPL)
+	disable_tlb(CONFIG_SYS_PPC_E500_DEBUG_TLB);
+#endif
+
 	init_tlbs();
 }
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index 288f7b2..bb95f3d 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -663,7 +663,7 @@
 #ifdef CONFIG_FSL_CORENET
 	do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-1.0",
 		"clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
-	do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-2",
+	do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-2.0",
 		"clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
 	do_fixup_by_compat_u32(blob, "fsl,mpic",
 		"clock-frequency", get_bus_freq(0)/2, 1);
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
index 6dadeb8..ec96e81 100644
--- a/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
@@ -228,7 +228,7 @@
 		break;
 	}
 
-	if (srds1_io_sel > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
 		return;
 	}
@@ -237,7 +237,7 @@
 		serdes1_prtcl_map |= (1 << lane_prtcl);
 	}
 
-	if (srds2_io_sel > ARRAY_SIZE(serdes2_cfg_tbl)) {
+	if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 		printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c
index 7c49097..3483366 100644
--- a/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c
@@ -68,7 +68,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
@@ -77,7 +77,7 @@
 		serdes1_prtcl_map |= (1 << lane_prtcl);
 	}
 
-	if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c
index 76288cd..c9eea15 100644
--- a/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c
@@ -53,7 +53,7 @@
 
 	debug("PORDEVSR[IO_SEL] = %x\n", srds1_cfg);
 
-	if (srds1_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds1_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL] = %d\n", srds1_cfg);
 		return ;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c
index 2582637..49a0290 100644
--- a/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c
@@ -53,7 +53,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c
index f480c26..7af6aff 100644
--- a/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c
@@ -62,7 +62,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c
index 2ff5d9a..fcccb52 100644
--- a/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c
@@ -57,7 +57,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/p1010_serdes.c b/arch/powerpc/cpu/mpc85xx/p1010_serdes.c
index e8a0387..1f7dba0 100644
--- a/arch/powerpc/cpu/mpc85xx/p1010_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p1010_serdes.c
@@ -54,7 +54,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
@@ -63,7 +63,7 @@
 		serdes1_prtcl_map |= (1 << lane_prtcl);
 	}
 
-	if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/p1021_serdes.c b/arch/powerpc/cpu/mpc85xx/p1021_serdes.c
index 1849c16..d6d2696 100644
--- a/arch/powerpc/cpu/mpc85xx/p1021_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p1021_serdes.c
@@ -73,7 +73,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/p1022_serdes.c b/arch/powerpc/cpu/mpc85xx/p1022_serdes.c
index e4c9c22..ed49920 100644
--- a/arch/powerpc/cpu/mpc85xx/p1022_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p1022_serdes.c
@@ -93,7 +93,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
@@ -102,7 +102,7 @@
 		serdes1_prtcl_map |= (1 << lane_prtcl);
 	}
 
-	if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/p1023_serdes.c b/arch/powerpc/cpu/mpc85xx/p1023_serdes.c
index c8ab5d6..0b4ae90 100644
--- a/arch/powerpc/cpu/mpc85xx/p1023_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p1023_serdes.c
@@ -41,7 +41,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/p2020_serdes.c b/arch/powerpc/cpu/mpc85xx/p2020_serdes.c
index 389ff6b..01af333 100644
--- a/arch/powerpc/cpu/mpc85xx/p2020_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p2020_serdes.c
@@ -61,7 +61,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/p2041_serdes.c b/arch/powerpc/cpu/mpc85xx/p2041_serdes.c
index eec4ffe..87335c9 100644
--- a/arch/powerpc/cpu/mpc85xx/p2041_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p2041_serdes.c
@@ -90,7 +90,7 @@
 	u32 svr = get_svr();
 	u32 ver = SVR_SOC_VER(svr);
 
-	if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
 		return 0;
 
 	/* P2040[e] does not support XAUI */
diff --git a/arch/powerpc/cpu/mpc85xx/p3041_serdes.c b/arch/powerpc/cpu/mpc85xx/p3041_serdes.c
index fba9ff2..a36dcd5 100644
--- a/arch/powerpc/cpu/mpc85xx/p3041_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p3041_serdes.c
@@ -139,7 +139,7 @@
 int is_serdes_prtcl_valid(u32 prtcl) {
 	int i;
 
-	if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
 		return 0;
 
 	for (i = 0; i < SRDS_MAX_LANES; i++) {
diff --git a/arch/powerpc/cpu/mpc85xx/p4080_serdes.c b/arch/powerpc/cpu/mpc85xx/p4080_serdes.c
index 87bd795..94ec445 100644
--- a/arch/powerpc/cpu/mpc85xx/p4080_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p4080_serdes.c
@@ -86,7 +86,7 @@
 int is_serdes_prtcl_valid(u32 prtcl) {
 	int i;
 
-	if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
 		return 0;
 
 	for (i = 0; i < SRDS_MAX_LANES; i++) {
diff --git a/arch/powerpc/cpu/mpc85xx/p5020_serdes.c b/arch/powerpc/cpu/mpc85xx/p5020_serdes.c
index fba9ff2..a36dcd5 100644
--- a/arch/powerpc/cpu/mpc85xx/p5020_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p5020_serdes.c
@@ -139,7 +139,7 @@
 int is_serdes_prtcl_valid(u32 prtcl) {
 	int i;
 
-	if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
 		return 0;
 
 	for (i = 0; i < SRDS_MAX_LANES; i++) {
diff --git a/arch/powerpc/cpu/mpc85xx/p5040_serdes.c b/arch/powerpc/cpu/mpc85xx/p5040_serdes.c
index 890b88e..d646e85 100644
--- a/arch/powerpc/cpu/mpc85xx/p5040_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/p5040_serdes.c
@@ -105,7 +105,7 @@
 {
 	int i;
 
-	if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
 		return 0;
 
 	for (i = 0; i < SRDS_MAX_LANES; i++) {
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index 4f0480b..2657982 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -1795,7 +1795,7 @@
 	stw	r0,0(r3)
 	addi	r3,r3,4
 	cmplw	0,r3,r4
-	bne	5b
+	blt	5b
 6:
 
 	mr	r3,r9		/* Init Data pointer		*/
diff --git a/arch/powerpc/cpu/mpc85xx/t1040_serdes.c b/arch/powerpc/cpu/mpc85xx/t1040_serdes.c
index 8261e03..19add9f 100644
--- a/arch/powerpc/cpu/mpc85xx/t1040_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/t1040_serdes.c
@@ -81,7 +81,7 @@
 {
 	int i;
 
-	if (prtcl > (ARRAY_SIZE(serdes_cfg_tbl[serdes])))
+	if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl[serdes]))
 		return 0;
 
 	for (i = 0; i < SRDS_MAX_LANES; i++) {
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
index f2b7bff..20284ed 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
@@ -26,6 +26,13 @@
 #include "config.h"	/* CONFIG_BOARDDIR */
 
 OUTPUT_ARCH(powerpc)
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+PHDRS
+{
+	text PT_LOAD;
+	bss PT_LOAD;
+}
+#endif
 SECTIONS
 {
 	. = CONFIG_SPL_TEXT_BASE;
@@ -60,7 +67,7 @@
 #if defined(CONFIG_FSL_IFC) /* Restrict bootpg at 4K boundry for IFC */
 	.bootpg ADDR(.text) + 0x1000 :
 	{
-		start.o	(.bootpg)
+		arch/powerpc/cpu/mpc85xx/start.o (.bootpg)
 	}
 #define RESET_VECTOR_OFFSET 0x1ffc /* IFC has 8K sram */
 #elif defined(CONFIG_FSL_ELBC)
@@ -68,9 +75,16 @@
 #else
 #error unknown NAND controller
 #endif
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+	.bootpg ADDR(.text) - 0x1000 :
+	{
+		KEEP(*(.bootpg))
+	} :text = 0xffff
+#else
 	.resetvec ADDR(.text) + RESET_VECTOR_OFFSET : {
 		KEEP(*(.resetvec))
 	} = 0xffff
+#endif
 
 	/*
 	 * Make sure that the bss segment isn't linked at 0x0, otherwise its
@@ -78,10 +92,12 @@
 	 */
 	. |= 0x10;
 
+	. = ALIGN(4);
 	__bss_start = .;
 	.bss : {
 		*(.sbss*)
 		*(.bss*)
 	}
+	. = ALIGN(4);
 	__bss_end = .;
 }
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot.lds b/arch/powerpc/cpu/mpc85xx/u-boot.lds
index 0503dce..2643563 100644
--- a/arch/powerpc/cpu/mpc85xx/u-boot.lds
+++ b/arch/powerpc/cpu/mpc85xx/u-boot.lds
@@ -95,6 +95,13 @@
   . = ALIGN(256);
   __init_end = .;
 
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+  .bootpg ADDR(.text) - 0x1000 :
+  {
+    KEEP(arch/powerpc/cpu/mpc85xx/start.o (.bootpg))
+  } :text = 0xffff
+  . = ADDR(.text) + 0x80000;
+#else
   .bootpg RESET_VECTOR_ADDRESS - 0xffc :
   {
     arch/powerpc/cpu/mpc85xx/start.o	(.bootpg)
@@ -117,6 +124,7 @@
 #if (RESET_VECTOR_ADDRESS == 0xfffffffc)
   . |= 0x10;
 #endif
+#endif
 
   __bss_start = .;
   .bss (NOLOAD)       :
diff --git a/arch/powerpc/cpu/mpc86xx/cpu.c b/arch/powerpc/cpu/mpc86xx/cpu.c
index c553415..5ed3eb2 100644
--- a/arch/powerpc/cpu/mpc86xx/cpu.c
+++ b/arch/powerpc/cpu/mpc86xx/cpu.c
@@ -78,7 +78,7 @@
 	major = PVR_E600_MAJ(pvr);
 	minor = PVR_E600_MIN(pvr);
 
-	printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 );
+	printf("e600 Core %d", (msscr0 & 0x20) ? 1 : 0);
 	if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE)
 		puts("\n    Core1Translation Enabled");
 	debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr);
diff --git a/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c b/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c
index 0dc1975..0342e34 100644
--- a/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c
+++ b/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c
@@ -64,7 +64,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
@@ -73,7 +73,7 @@
 		serdes1_prtcl_map |= (1 << lane_prtcl);
 	}
 
-	if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c b/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c
index 3ae9069..21c5ddb 100644
--- a/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c
+++ b/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c
@@ -73,7 +73,7 @@
 
 	debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-	if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
@@ -82,7 +82,7 @@
 		serdes1_prtcl_map |= (1 << lane_prtcl);
 	}
 
-	if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+	if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
 		printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
 		return;
 	}
diff --git a/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c b/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
index 56b319f..4e8a441 100644
--- a/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
+++ b/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
@@ -26,7 +26,7 @@
 	int i, j;
 
 	printf("IFC Controller Registers\n");
-	for (i = 0; i < FSL_IFC_BANK_COUNT; i++) {
+	for (i = 0; i < CONFIG_SYS_FSL_IFC_BANK_COUNT; i++) {
 		printf("CSPR%d:0x%08X\tAMASK%d:0x%08X\tCSOR%d:0x%08X\n",
 			i, get_ifc_cspr(i), i, get_ifc_amask(i),
 			i, get_ifc_csor(i));
@@ -43,7 +43,7 @@
 	set_ifc_ftim(IFC_CS0, IFC_FTIM2, CONFIG_SYS_CS0_FTIM2);
 	set_ifc_ftim(IFC_CS0, IFC_FTIM3, CONFIG_SYS_CS0_FTIM3);
 
-#if !defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) || defined(CONFIG_SYS_RAMBOOT)
+#ifndef CONFIG_A003399_NOR_WORKAROUND
 #ifdef CONFIG_SYS_CSPR0_EXT
 	set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT);
 #endif
@@ -94,4 +94,60 @@
 	set_ifc_amask(IFC_CS3, CONFIG_SYS_AMASK3);
 	set_ifc_csor(IFC_CS3, CONFIG_SYS_CSOR3);
 #endif
+
+#ifdef CONFIG_SYS_CSPR4_EXT
+	set_ifc_cspr_ext(IFC_CS4, CONFIG_SYS_CSPR4_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR4) && defined(CONFIG_SYS_CSOR4)
+	set_ifc_ftim(IFC_CS4, IFC_FTIM0, CONFIG_SYS_CS4_FTIM0);
+	set_ifc_ftim(IFC_CS4, IFC_FTIM1, CONFIG_SYS_CS4_FTIM1);
+	set_ifc_ftim(IFC_CS4, IFC_FTIM2, CONFIG_SYS_CS4_FTIM2);
+	set_ifc_ftim(IFC_CS4, IFC_FTIM3, CONFIG_SYS_CS4_FTIM3);
+
+	set_ifc_cspr(IFC_CS4, CONFIG_SYS_CSPR4);
+	set_ifc_amask(IFC_CS4, CONFIG_SYS_AMASK4);
+	set_ifc_csor(IFC_CS4, CONFIG_SYS_CSOR4);
+#endif
+
+#ifdef CONFIG_SYS_CSPR5_EXT
+	set_ifc_cspr_ext(IFC_CS5, CONFIG_SYS_CSPR5_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR5) && defined(CONFIG_SYS_CSOR5)
+	set_ifc_ftim(IFC_CS5, IFC_FTIM0, CONFIG_SYS_CS5_FTIM0);
+	set_ifc_ftim(IFC_CS5, IFC_FTIM1, CONFIG_SYS_CS5_FTIM1);
+	set_ifc_ftim(IFC_CS5, IFC_FTIM2, CONFIG_SYS_CS5_FTIM2);
+	set_ifc_ftim(IFC_CS5, IFC_FTIM3, CONFIG_SYS_CS5_FTIM3);
+
+	set_ifc_cspr(IFC_CS5, CONFIG_SYS_CSPR5);
+	set_ifc_amask(IFC_CS5, CONFIG_SYS_AMASK5);
+	set_ifc_csor(IFC_CS5, CONFIG_SYS_CSOR5);
+#endif
+
+#ifdef CONFIG_SYS_CSPR6_EXT
+	set_ifc_cspr_ext(IFC_CS6, CONFIG_SYS_CSPR6_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR6) && defined(CONFIG_SYS_CSOR6)
+	set_ifc_ftim(IFC_CS6, IFC_FTIM0, CONFIG_SYS_CS6_FTIM0);
+	set_ifc_ftim(IFC_CS6, IFC_FTIM1, CONFIG_SYS_CS6_FTIM1);
+	set_ifc_ftim(IFC_CS6, IFC_FTIM2, CONFIG_SYS_CS6_FTIM2);
+	set_ifc_ftim(IFC_CS6, IFC_FTIM3, CONFIG_SYS_CS6_FTIM3);
+
+	set_ifc_cspr(IFC_CS6, CONFIG_SYS_CSPR6);
+	set_ifc_amask(IFC_CS6, CONFIG_SYS_AMASK6);
+	set_ifc_csor(IFC_CS6, CONFIG_SYS_CSOR6);
+#endif
+
+#ifdef CONFIG_SYS_CSPR7_EXT
+	set_ifc_cspr_ext(IFC_CS7, CONFIG_SYS_CSPR7_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR7) && defined(CONFIG_SYS_CSOR7)
+	set_ifc_ftim(IFC_CS7, IFC_FTIM0, CONFIG_SYS_CS7_FTIM0);
+	set_ifc_ftim(IFC_CS7, IFC_FTIM1, CONFIG_SYS_CS7_FTIM1);
+	set_ifc_ftim(IFC_CS7, IFC_FTIM2, CONFIG_SYS_CS7_FTIM2);
+	set_ifc_ftim(IFC_CS7, IFC_FTIM3, CONFIG_SYS_CS7_FTIM3);
+
+	set_ifc_cspr(IFC_CS7, CONFIG_SYS_CSPR7);
+	set_ifc_amask(IFC_CS7, CONFIG_SYS_AMASK7);
+	set_ifc_csor(IFC_CS7, CONFIG_SYS_CSOR7);
+#endif
 }
diff --git a/arch/powerpc/cpu/mpc8xxx/srio.c b/arch/powerpc/cpu/mpc8xxx/srio.c
index 6e6f7dc..90d1065 100644
--- a/arch/powerpc/cpu/mpc8xxx/srio.c
+++ b/arch/powerpc/cpu/mpc8xxx/srio.c
@@ -24,7 +24,7 @@
 #include <asm/fsl_srio.h>
 #include <asm/errno.h>
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 #define SRIO_PORT_ACCEPT_ALL 0x10000001
 #define SRIO_IB_ATMU_AR 0x80f55000
 #define SRIO_OB_ATMU_AR_MAINT 0x80077000
@@ -299,7 +299,7 @@
 	}
 }
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 void srio_boot_master(int port)
 {
 	struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR;
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 1009a31..1d46b14 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -139,6 +139,7 @@
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_NUM_DDR_CONTROLLERS	1
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT	4
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.2"
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
@@ -337,7 +338,6 @@
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM	9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM	5
@@ -371,7 +371,6 @@
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM	9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM	5
@@ -413,7 +412,6 @@
 #define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM	9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM	5
@@ -449,7 +447,6 @@
 #define CONFIG_SYS_FSL_ERRATUM_USB14
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM	9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM	5
@@ -494,6 +491,9 @@
 #define CONFIG_TSECV2
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_NUM_DDR_CONTROLLERS	1
+#define CONFIG_SYS_FSL_DSP_M2_RAM_ADDR	0xb0000000
+#define CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT	0xff600000
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT	3
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
 #define CONFIG_NAND_FSL_IFC
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -506,6 +506,7 @@
 #define CONFIG_TSECV2
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_NUM_DDR_CONTROLLERS	2
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT	3
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
 #define CONFIG_NAND_FSL_IFC
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -541,6 +542,7 @@
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_SYS_NUM_FMAN		2
 #define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT	8
 #define CONFIG_SYS_FMAN_V3
 #define CONFIG_SYS_FM_MURAM_SIZE	0x60000
 #define CONFIG_SYS_FSL_TBCLK_DIV	16
@@ -553,6 +555,7 @@
 #define CONFIG_SYS_FSL_ERRATUM_A004468
 #define CONFIG_SYS_FSL_ERRATUM_A_004934
 #define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006593
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xfe000000
 #define CONFIG_SYS_FSL_PCI_VER_3_X
 
@@ -566,6 +569,7 @@
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_SYS_NUM_FMAN		1
 #define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT	4
 #define CONFIG_SYS_FMAN_V3
 #define CONFIG_SYS_FM_MURAM_SIZE	0x60000
 #define CONFIG_SYS_FSL_TBCLK_DIV	16
@@ -573,6 +577,7 @@
 #define CONFIG_SYS_FSL_USB1_PHY_ENABLE
 #define CONFIG_SYS_FSL_ERRATUM_A_004934
 #define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006593
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xfe000000
 
 #ifdef CONFIG_PPC_B4860
diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h
index ba41b73..3baf4cc 100644
--- a/arch/powerpc/include/asm/fsl_ifc.h
+++ b/arch/powerpc/include/asm/fsl_ifc.h
@@ -21,6 +21,7 @@
 #ifndef __ASM_PPC_FSL_IFC_H
 #define __ASM_PPC_FSL_IFC_H
 
+#ifdef CONFIG_FSL_IFC
 #include <config.h>
 #include <common.h>
 
@@ -798,13 +799,15 @@
 #define set_ifc_ftim(i, j, v) \
 			(out_be32(&(IFC_BASE_ADDR)->ftim_cs[i].ftim[j], v))
 
-#define FSL_IFC_BANK_COUNT	4
-
 enum ifc_chip_sel {
 	IFC_CS0,
 	IFC_CS1,
 	IFC_CS2,
 	IFC_CS3,
+	IFC_CS4,
+	IFC_CS5,
+	IFC_CS6,
+	IFC_CS7,
 };
 
 enum ifc_ftims {
@@ -907,6 +910,49 @@
 	u32 res4[0x1F3];
 };
 
+#ifdef CONFIG_SYS_FSL_IFC_BANK_COUNT
+#if (CONFIG_SYS_FSL_IFC_BANK_COUNT <= 8)
+#define IFC_CSPR_REG_LEN	148
+#define IFC_AMASK_REG_LEN	144
+#define IFC_CSOR_REG_LEN	144
+#define IFC_FTIM_REG_LEN	576
+
+#define IFC_CSPR_USED_LEN	sizeof(struct fsl_ifc_cspr) * \
+					CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_AMASK_USED_LEN	sizeof(struct fsl_ifc_amask) * \
+					CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_CSOR_USED_LEN	sizeof(struct fsl_ifc_csor) * \
+					CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_FTIM_USED_LEN	sizeof(struct fsl_ifc_ftim) * \
+					CONFIG_SYS_FSL_IFC_BANK_COUNT
+#else
+#error IFC BANK count not vaild
+#endif
+#else
+#error IFC BANK count not defined
+#endif
+
+struct fsl_ifc_cspr {
+	u32 cspr_ext;
+	u32 cspr;
+	u32 res;
+};
+
+struct fsl_ifc_amask {
+	u32 amask;
+	u32 res[0x2];
+};
+
+struct fsl_ifc_csor {
+	u32 csor;
+	u32 csor_ext;
+	u32 res;
+};
+
+struct fsl_ifc_ftim {
+	u32 ftim[4];
+	u32 res[0x8];
+};
 
 /*
  * IFC Controller Registers
@@ -914,44 +960,30 @@
 struct fsl_ifc {
 	u32 ifc_rev;
 	u32 res1[0x2];
-	struct {
-		u32 cspr_ext;
-		u32 cspr;
-		u32 res2;
-	} cspr_cs[FSL_IFC_BANK_COUNT];
-	u32 res3[0x19];
-	struct {
-		u32 amask;
-		u32 res4[0x2];
-	} amask_cs[FSL_IFC_BANK_COUNT];
-	u32 res5[0x17];
-	struct {
-		u32 csor_ext;
-		u32 csor;
-		u32 res6;
-	} csor_cs[FSL_IFC_BANK_COUNT];
-	u32 res7[0x19];
-	struct {
-		u32 ftim[4];
-		u32 res8[0x8];
-	} ftim_cs[FSL_IFC_BANK_COUNT];
-	u32 res9[0x60];
+	struct fsl_ifc_cspr cspr_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+	u8 res2[IFC_CSPR_REG_LEN - IFC_CSPR_USED_LEN];
+	struct fsl_ifc_amask amask_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+	u8 res3[IFC_AMASK_REG_LEN - IFC_AMASK_USED_LEN];
+	struct fsl_ifc_csor csor_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+	u8 res4[IFC_CSOR_REG_LEN - IFC_CSOR_USED_LEN];
+	struct fsl_ifc_ftim ftim_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+	u8 res5[IFC_FTIM_REG_LEN - IFC_FTIM_USED_LEN];
 	u32 rb_stat;
-	u32 res10[0x2];
+	u32 res6[0x2];
 	u32 ifc_gcr;
-	u32 res11[0x2];
+	u32 res7[0x2];
 	u32 cm_evter_stat;
-	u32 res12[0x2];
+	u32 res8[0x2];
 	u32 cm_evter_en;
-	u32 res13[0x2];
+	u32 res9[0x2];
 	u32 cm_evter_intr_en;
-	u32 res14[0x2];
+	u32 res10[0x2];
 	u32 cm_erattr0;
 	u32 cm_erattr1;
-	u32 res15[0x2];
+	u32 res11[0x2];
 	u32 ifc_ccr;
 	u32 ifc_csr;
-	u32 res16[0x2EB];
+	u32 res12[0x2EB];
 	struct fsl_ifc_nand ifc_nand;
 	struct fsl_ifc_nor ifc_nor;
 	struct fsl_ifc_gpcm ifc_gpcm;
@@ -961,6 +993,7 @@
 #undef CSPR_MSEL_NOR
 #define CSPR_MSEL_NOR	CSPR_MSEL_GPCM
 #endif
+#endif /* CONFIG_FSL_IFC */
 
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_PPC_FSL_IFC_H */
diff --git a/arch/powerpc/include/asm/fsl_law.h b/arch/powerpc/include/asm/fsl_law.h
index 90b264d..bea1636 100644
--- a/arch/powerpc/include/asm/fsl_law.h
+++ b/arch/powerpc/include/asm/fsl_law.h
@@ -82,11 +82,16 @@
 #ifndef CONFIG_MPC8641
 	LAW_TRGT_IF_PCIE_1 = 0x02,
 #endif
+#if defined(CONFIG_BSC9131)
+	LAW_TRGT_IF_OCN_DSP = 0x03,
+#else
 #if !defined(CONFIG_MPC8572) && !defined(CONFIG_P2020)
 	LAW_TRGT_IF_PCIE_3 = 0x03,
 #endif
+#endif
 	LAW_TRGT_IF_LBC = 0x04,
 	LAW_TRGT_IF_CCSR = 0x08,
+	LAW_TRGT_IF_DSP_CCSR = 0x09,
 	LAW_TRGT_IF_DDR_INTRLV = 0x0b,
 	LAW_TRGT_IF_RIO = 0x0c,
 	LAW_TRGT_IF_RIO_2 = 0x0d,
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index 4052037..db70d04 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -1839,11 +1839,13 @@
 #define FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT	11
 #define FSL_CORENET2_RCWSR4_SRDS4_PRTCL		0x000000f8
 #define FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT	3
+#define FSL_CORENET_RCWSR6_BOOT_LOC	0x0f800000
 #elif defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_B4420)
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL	0xfe000000
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT	25
 #define FSL_CORENET2_RCWSR4_SRDS2_PRTCL	0x00ff0000
 #define FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT	16
+#define FSL_CORENET_RCWSR6_BOOT_LOC	0x0f800000
 #elif defined(CONFIG_PPC_T1040)
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL	0xff000000
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT	24
@@ -2160,7 +2162,7 @@
 	u32	porbmsr;	/* POR boot mode status */
 #define MPC85xx_PORBMSR_HA		0x00070000
 #define MPC85xx_PORBMSR_HA_SHIFT	16
-#define MPC85XX_PORBMSR_ROMLOC_SHIFT	24
+#define MPC85xx_PORBMSR_ROMLOC_SHIFT	24
 #define PORBMSR_ROMLOC_SPI	0x6
 #define PORBMSR_ROMLOC_SDHC	0x7
 #define PORBMSR_ROMLOC_NAND_2K	0x9
diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c
index dd6c98c..d4ad323 100644
--- a/arch/powerpc/lib/bootm.c
+++ b/arch/powerpc/lib/bootm.c
@@ -256,11 +256,6 @@
 		return 0;
 	}
 
-	if (flag & BOOTM_STATE_OS_GO) {
-		boot_jump_linux(images);
-		return 0;
-	}
-
 	boot_prep_linux(images);
 	ret = boot_body_linux(images);
 	if (ret)
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index dd8d495..e9385de 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -37,7 +37,7 @@
 	os_usleep(usec);
 }
 
-unsigned long timer_get_us(void)
+unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
 {
 	return os_get_nsec() / 1000;
 }
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index d075407..541e450 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -152,7 +152,7 @@
 	usleep(usec);
 }
 
-u64 os_get_nsec(void)
+u64 __attribute__((no_instrument_function)) os_get_nsec(void)
 {
 #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
 	struct timespec tp;
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 4fdb080..9a2056a 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -40,7 +40,7 @@
 #include <asm-generic/global_data.h>
 
 #ifndef __ASSEMBLY__
-static inline gd_t *get_fs_gd_ptr(void)
+static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void)
 {
 	gd_t *gd_ptr;
 
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 6030633..b459a63 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -85,7 +85,8 @@
 #define EAX_EDX_RET(val, low, high)	"=A" (val)
 #endif
 
-static inline unsigned long long native_read_msr(unsigned int msr)
+static inline __attribute__((no_instrument_function))
+	unsigned long long native_read_msr(unsigned int msr)
 {
 	DECLARE_ARGS(val, low, high);
 
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 22e0934..709dc84 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -64,7 +64,7 @@
 void	board_init_f_r(void) __attribute__ ((noreturn));
 
 /* Read the time stamp counter */
-static inline uint64_t rdtsc(void)
+static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void)
 {
 	uint32_t high, low;
 	__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 2520228..0d3250c 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -63,6 +63,8 @@
 		}
 #if defined(CONFIG_FIT)
 	} else if (images->fit_uname_os) {
+		int ret;
+
 		ret = fit_image_get_data(images->fit_hdr_os,
 					images->fit_noffset_os, &data, &len);
 		if (ret) {
diff --git a/arch/x86/lib/gcc.c b/arch/x86/lib/gcc.c
index 4043431..497ad75 100644
--- a/arch/x86/lib/gcc.c
+++ b/arch/x86/lib/gcc.c
@@ -28,7 +28,9 @@
 #define WRAP_LIBGCC_CALL(type, name) \
 	type __normal_##name(type a, type b) __attribute__((regparm(0))); \
 	type __wrap_##name(type a, type b); \
-	type __wrap_##name(type a, type b) { return __normal_##name(a, b); }
+	type __attribute__((no_instrument_function)) \
+		__wrap_##name(type a, type b) \
+		 { return __normal_##name(a, b); }
 
 WRAP_LIBGCC_CALL(long long, __divdi3)
 WRAP_LIBGCC_CALL(unsigned long long, __udivdi3)
diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c
index c509801..0688973 100644
--- a/arch/x86/lib/tsc_timer.c
+++ b/arch/x86/lib/tsc_timer.c
@@ -37,7 +37,7 @@
  * restart. This yields a free running counter guaranteed to take almost 6
  * years to wrap around even at 100GHz clock rate.
  */
-u64 get_ticks(void)
+u64 __attribute__((no_instrument_function)) get_ticks(void)
 {
 	u64 now_tick = rdtsc();
 
@@ -50,7 +50,7 @@
 #define PLATFORM_INFO_MSR 0xce
 
 /* Get the speed of the TSC timer in MHz */
-unsigned long get_tbclk_mhz(void)
+unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
 {
 	u32 ratio;
 	u64 platform_info = native_read_msr(PLATFORM_INFO_MSR);
@@ -75,7 +75,7 @@
 	return get_ms_timer() - base;
 }
 
-ulong timer_get_us(void)
+ulong __attribute__((no_instrument_function)) timer_get_us(void)
 {
 	return get_ticks() / get_tbclk_mhz();
 }
diff --git a/board/LaCie/common/cpld-gpio-bus.c b/board/LaCie/common/cpld-gpio-bus.c
new file mode 100644
index 0000000..fb9bf8d
--- /dev/null
+++ b/board/LaCie/common/cpld-gpio-bus.c
@@ -0,0 +1,50 @@
+/*
+ * cpld-gpio-bus.c: provides support for the CPLD GPIO bus found on some LaCie
+ * boards (as the 2Big/5Big Network v2 and the 2Big NAS). This parallel GPIO
+ * bus exposes two registers (address and data). Each of this register is made
+ * up of several dedicated GPIOs. An extra GPIO is used to notify the CPLD that
+ * the registers have been updated.
+ *
+ * Mostly this bus is used to configure the LEDs on LaCie boards.
+ *
+ * Copyright (C) 2013 Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * 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.
+ */
+
+#include <asm/arch/gpio.h>
+#include "cpld-gpio-bus.h"
+
+static void cpld_gpio_bus_set_addr(struct cpld_gpio_bus *bus, unsigned addr)
+{
+	int pin;
+
+	for (pin = 0; pin < bus->num_addr; pin++)
+		kw_gpio_set_value(bus->addr[pin], (addr >> pin) & 1);
+}
+
+static void cpld_gpio_bus_set_data(struct cpld_gpio_bus *bus, unsigned data)
+{
+	int pin;
+
+	for (pin = 0; pin < bus->num_data; pin++)
+		kw_gpio_set_value(bus->data[pin], (data >> pin) & 1);
+}
+
+static void cpld_gpio_bus_enable_select(struct cpld_gpio_bus *bus)
+{
+	/* The transfer is enabled on the raising edge. */
+	kw_gpio_set_value(bus->enable, 0);
+	kw_gpio_set_value(bus->enable, 1);
+}
+
+void cpld_gpio_bus_write(struct cpld_gpio_bus *bus,
+			 unsigned addr, unsigned value)
+{
+	cpld_gpio_bus_set_addr(bus, addr);
+	cpld_gpio_bus_set_data(bus, value);
+	cpld_gpio_bus_enable_select(bus);
+}
diff --git a/board/LaCie/common/cpld-gpio-bus.h b/board/LaCie/common/cpld-gpio-bus.h
new file mode 100644
index 0000000..e9e9b96
--- /dev/null
+++ b/board/LaCie/common/cpld-gpio-bus.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * 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.
+ */
+
+#ifndef _LACIE_CPLD_GPI0_BUS_H
+#define _LACIE_CPLD_GPI0_BUS_H
+
+struct cpld_gpio_bus {
+	unsigned *addr;
+	unsigned num_addr;
+	unsigned *data;
+	unsigned num_data;
+	unsigned enable;
+};
+
+void cpld_gpio_bus_write(struct cpld_gpio_bus *cpld_gpio_bus,
+			 unsigned addr, unsigned value);
+
+#endif /* _LACIE_CPLD_GPI0_BUS_H */
diff --git a/board/LaCie/net2big_v2/Makefile b/board/LaCie/net2big_v2/Makefile
index fbae48e..9a6dfb6 100644
--- a/board/LaCie/net2big_v2/Makefile
+++ b/board/LaCie/net2big_v2/Makefile
@@ -28,6 +28,9 @@
 LIB	= $(obj)lib$(BOARD).o
 
 COBJS	:= $(BOARD).o ../common/common.o
+ifneq ($(and $(CONFIG_KIRKWOOD_GPIO),$(CONFIG_NET2BIG_V2)),)
+COBJS	+= ../common/cpld-gpio-bus.o
+endif
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
diff --git a/board/LaCie/net2big_v2/net2big_v2.c b/board/LaCie/net2big_v2/net2big_v2.c
index e524f35..b133f7c 100644
--- a/board/LaCie/net2big_v2/net2big_v2.c
+++ b/board/LaCie/net2big_v2/net2big_v2.c
@@ -22,6 +22,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <i2c.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/kirkwood.h>
 #include <asm/arch/mpp.h>
@@ -29,6 +30,7 @@
 
 #include "net2big_v2.h"
 #include "../common/common.h"
+#include "../common/cpld-gpio-bus.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -60,18 +62,18 @@
 		MPP24_GPIO,		/* USB mode select */
 		MPP26_GPIO,		/* USB device vbus */
 		MPP28_GPIO,		/* USB enable host vbus */
-		MPP29_GPIO,		/* GPIO extension ALE */
+		MPP29_GPIO,		/* CPLD GPIO bus ALE */
 		MPP34_GPIO,		/* Rear Push button 0=on 1=off */
 		MPP35_GPIO,		/* Inhibit switch power-off */
 		MPP36_GPIO,		/* SATA HDD1 presence */
 		MPP37_GPIO,		/* SATA HDD2 presence */
 		MPP40_GPIO,		/* eSATA presence */
-		MPP44_GPIO,		/* GPIO extension (data 0) */
-		MPP45_GPIO,		/* GPIO extension (data 1) */
-		MPP46_GPIO,		/* GPIO extension (data 2) */
-		MPP47_GPIO,		/* GPIO extension (addr 0) */
-		MPP48_GPIO,		/* GPIO extension (addr 1) */
-		MPP49_GPIO,		/* GPIO extension (addr 2) */
+		MPP44_GPIO,		/* CPLD GPIO bus (data 0) */
+		MPP45_GPIO,		/* CPLD GPIO bus (data 1) */
+		MPP46_GPIO,		/* CPLD GPIO bus (data 2) */
+		MPP47_GPIO,		/* CPLD GPIO bus (addr 0) */
+		MPP48_GPIO,		/* CPLD GPIO bus (addr 1) */
+		MPP49_GPIO,		/* CPLD GPIO bus (addr 2) */
 		0
 	};
 
@@ -92,8 +94,142 @@
 }
 
 #if defined(CONFIG_MISC_INIT_R)
+
+#if defined(CONFIG_CMD_I2C) && defined(CONFIG_SYS_I2C_G762_ADDR)
+/*
+ * Start I2C fan (GMT G762 controller)
+ */
+static void init_fan(void)
+{
+	u8 data;
+
+	i2c_set_bus_num(0);
+
+	/* Enable open-loop and PWM modes */
+	data = 0x20;
+	if (i2c_write(CONFIG_SYS_I2C_G762_ADDR,
+		      G762_REG_FAN_CMD1, 1, &data, 1) != 0)
+		goto err;
+	data = 0;
+	if (i2c_write(CONFIG_SYS_I2C_G762_ADDR,
+		      G762_REG_SET_CNT, 1, &data, 1) != 0)
+		goto err;
+	/*
+	 * RPM to PWM (set_out register) fan speed conversion array:
+	 * 0    0x00
+	 * 1500	0x04
+	 * 2800	0x08
+	 * 3400	0x0C
+	 * 3700	0x10
+	 * 4400	0x20
+	 * 4700	0x30
+	 * 4800	0x50
+	 * 5200	0x80
+	 * 5400	0xC0
+	 * 5500	0xFF
+	 *
+	 * Start fan at low speed (2800 RPM):
+	 */
+	data = 0x08;
+	if (i2c_write(CONFIG_SYS_I2C_G762_ADDR,
+		      G762_REG_SET_OUT, 1, &data, 1) != 0)
+		goto err;
+
+	return;
+err:
+	printf("Error: failed to start I2C fan @%02x\n",
+	       CONFIG_SYS_I2C_G762_ADDR);
+}
+#else
+static void init_fan(void) {}
+#endif /* CONFIG_CMD_I2C && CONFIG_SYS_I2C_G762_ADDR */
+
+#if defined(CONFIG_NET2BIG_V2) && defined(CONFIG_KIRKWOOD_GPIO)
+/*
+ * CPLD GPIO bus:
+ *
+ * - address register : bit [0-2] -> GPIO [47-49]
+ * - data register    : bit [0-2] -> GPIO [44-46]
+ * - enable register  : GPIO 29
+ */
+static unsigned cpld_gpio_bus_addr[] = { 47, 48, 49 };
+static unsigned cpld_gpio_bus_data[] = { 44, 45, 46 };
+
+static struct cpld_gpio_bus cpld_gpio_bus = {
+	.addr		= cpld_gpio_bus_addr,
+	.num_addr	= ARRAY_SIZE(cpld_gpio_bus_addr),
+	.data		= cpld_gpio_bus_data,
+	.num_data	= ARRAY_SIZE(cpld_gpio_bus_data),
+	.enable		= 29,
+};
+
+/*
+ * LEDs configuration:
+ *
+ * The LEDs are controlled by a CPLD and can be configured through
+ * the CPLD GPIO bus.
+ *
+ * Address register selection:
+ *
+ * addr | register
+ * ----------------------------
+ *   0  | front LED
+ *   1  | front LED brightness
+ *   2  | SATA LED brightness
+ *   3  | SATA0 LED
+ *   4  | SATA1 LED
+ *   5  | SATA2 LED
+ *   6  | SATA3 LED
+ *   7  | SATA4 LED
+ *
+ * Data register configuration:
+ *
+ * data | LED brightness
+ * -------------------------------------------------
+ *   0  | min (off)
+ *   -  | -
+ *   7  | max
+ *
+ * data | front LED mode
+ * -------------------------------------------------
+ *   0  | fix off
+ *   1  | fix blue on
+ *   2  | fix red on
+ *   3  | blink blue on=1 sec and blue off=1 sec
+ *   4  | blink red on=1 sec and red off=1 sec
+ *   5  | blink blue on=2.5 sec and red on=0.5 sec
+ *   6  | blink blue on=1 sec and red on=1 sec
+ *   7  | blink blue on=0.5 sec and blue off=2.5 sec
+ *
+ * data | SATA LED mode
+ * -------------------------------------------------
+ *   0  | fix off
+ *   1  | SATA activity blink
+ *   2  | fix red on
+ *   3  | blink blue on=1 sec and blue off=1 sec
+ *   4  | blink red on=1 sec and red off=1 sec
+ *   5  | blink blue on=2.5 sec and red on=0.5 sec
+ *   6  | blink blue on=1 sec and red on=1 sec
+ *   7  | fix blue on
+ */
+static void init_leds(void)
+{
+	/* Enable the front blue LED */
+	cpld_gpio_bus_write(&cpld_gpio_bus, 0, 1);
+	cpld_gpio_bus_write(&cpld_gpio_bus, 1, 3);
+
+	/* Configure SATA LEDs to blink in relation with the SATA activity */
+	cpld_gpio_bus_write(&cpld_gpio_bus, 3, 1);
+	cpld_gpio_bus_write(&cpld_gpio_bus, 4, 1);
+	cpld_gpio_bus_write(&cpld_gpio_bus, 2, 3);
+}
+#else
+static void init_leds(void) {}
+#endif /* CONFIG_NET2BIG_V2 && CONFIG_KIRKWOOD_GPIO */
+
 int misc_init_r(void)
 {
+	init_fan();
 #if defined(CONFIG_CMD_I2C) && defined(CONFIG_SYS_I2C_EEPROM_ADDR)
 	if (!getenv("ethaddr")) {
 		uchar mac[6];
@@ -101,9 +237,11 @@
 			eth_setenv_enetaddr("ethaddr", mac);
 	}
 #endif
+	init_leds();
+
 	return 0;
 }
-#endif
+#endif /* CONFIG_MISC_INIT_R */
 
 #if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
 /* Configure and initialize PHY */
diff --git a/board/LaCie/net2big_v2/net2big_v2.h b/board/LaCie/net2big_v2/net2big_v2.h
index f9778f4..83537d6 100644
--- a/board/LaCie/net2big_v2/net2big_v2.h
+++ b/board/LaCie/net2big_v2/net2big_v2.h
@@ -32,4 +32,9 @@
 /* Buttons */
 #define NET2BIG_V2_GPIO_PUSH_BUTTON	34
 
+/* GMT G762 registers (I2C fan controller) */
+#define G762_REG_SET_CNT		0x00
+#define G762_REG_SET_OUT		0x03
+#define G762_REG_FAN_CMD1		0x04
+
 #endif /* NET2BIG_V2_H */
diff --git a/board/actux1/u-boot.lds b/board/actux1/u-boot.lds
index ef4a25b..74aec5f 100644
--- a/board/actux1/u-boot.lds
+++ b/board/actux1/u-boot.lds
@@ -30,6 +30,7 @@
 
 	. = ALIGN (4);
 	.text : {
+		*(.__image_copy_start)
 		arch/arm/cpu/ixp/start.o(.text*)
 		net/libnet.o(.text*)
 		board/actux1/libactux1.o(.text*)
@@ -62,17 +63,23 @@
 
 	. = ALIGN (4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -96,6 +103,7 @@
 		KEEP(*(.__bss_end));
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/board/actux2/u-boot.lds b/board/actux2/u-boot.lds
index 00ad8b7..c276501 100644
--- a/board/actux2/u-boot.lds
+++ b/board/actux2/u-boot.lds
@@ -30,6 +30,7 @@
 
 	. = ALIGN (4);
 	.text : {
+		*(.__image_copy_start)
 		arch/arm/cpu/ixp/start.o(.text*)
 		net/libnet.o(.text*)
 		board/actux2/libactux2.o(.text*)
@@ -62,17 +63,23 @@
 
 	. = ALIGN (4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -96,6 +103,7 @@
 		KEEP(*(.__bss_end));
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/board/actux3/u-boot.lds b/board/actux3/u-boot.lds
index 44b990e..5610644 100644
--- a/board/actux3/u-boot.lds
+++ b/board/actux3/u-boot.lds
@@ -30,6 +30,7 @@
 
 	. = ALIGN (4);
 	.text : {
+		*(.__image_copy_start)
 		arch/arm/cpu/ixp/start.o(.text*)
 		net/libnet.o(.text*)
 		board/actux3/libactux3.o(.text*)
@@ -62,17 +63,23 @@
 
 	. = ALIGN (4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -96,6 +103,7 @@
 		KEEP(*(.__bss_end));
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/board/ait/cam_enc_4xx/u-boot-spl.lds b/board/ait/cam_enc_4xx/u-boot-spl.lds
index 1daa1b3..3972685 100644
--- a/board/ait/cam_enc_4xx/u-boot-spl.lds
+++ b/board/ait/cam_enc_4xx/u-boot-spl.lds
@@ -54,11 +54,6 @@
 		__rel_dyn_end = .;
 	} >.sram
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	} >.sram
-
 	.bss :
 	{
 		. = ALIGN(4);
diff --git a/board/atmel/at91sam9n12ek/at91sam9n12ek.c b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
index 8752794..3013a42 100644
--- a/board/atmel/at91sam9n12ek/at91sam9n12ek.c
+++ b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
@@ -33,6 +33,7 @@
 #include <lcd.h>
 #include <atmel_hlcdc.h>
 #include <atmel_mci.h>
+#include <netdev.h>
 
 #ifdef CONFIG_LCD_INFO
 #include <nand.h>
@@ -190,6 +191,30 @@
 }
 #endif
 
+#ifdef CONFIG_KS8851_MLL
+void at91sam9n12ek_ks8851_hw_init(void)
+{
+	struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+
+	writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(0) |
+	       AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(0),
+	       &smc->cs[2].setup);
+	writel(AT91_SMC_PULSE_NWE(7) | AT91_SMC_PULSE_NCS_WR(7) |
+	       AT91_SMC_PULSE_NRD(7) | AT91_SMC_PULSE_NCS_RD(7),
+	       &smc->cs[2].pulse);
+	writel(AT91_SMC_CYCLE_NWE(9) | AT91_SMC_CYCLE_NRD(9),
+	       &smc->cs[2].cycle);
+	writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+	       AT91_SMC_MODE_EXNW_DISABLE |
+	       AT91_SMC_MODE_BAT | AT91_SMC_MODE_DBW_16 |
+	       AT91_SMC_MODE_TDF_CYCLE(1),
+	       &smc->cs[2].mode);
+
+	/* Configure NCS2 PIN */
+	at91_set_b_periph(AT91_PIO_PORTD, 19, 0);
+}
+#endif
+
 int board_early_init_f(void)
 {
 	/* Enable clocks for all PIOs */
@@ -217,9 +242,20 @@
 	at91_lcd_hw_init();
 #endif
 
+#ifdef CONFIG_KS8851_MLL
+	at91sam9n12ek_ks8851_hw_init();
+#endif
+
 	return 0;
 }
 
+#ifdef CONFIG_KS8851_MLL
+int board_eth_init(bd_t *bis)
+{
+	return ks8851_mll_initialize(0, CONFIG_KS8851_MLL_BASEADDR);
+}
+#endif
+
 int dram_init(void)
 {
 	gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
diff --git a/board/davinci/da8xxevm/u-boot-spl-da850evm.lds b/board/davinci/da8xxevm/u-boot-spl-da850evm.lds
index b1b8701..6fa4509 100644
--- a/board/davinci/da8xxevm/u-boot-spl-da850evm.lds
+++ b/board/davinci/da8xxevm/u-boot-spl-da850evm.lds
@@ -55,11 +55,6 @@
 		__rel_dyn_end = .;
 	} >.sram
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	} >.sram
-
 	.bss :
 	{
 		. = ALIGN(4);
diff --git a/board/davinci/da8xxevm/u-boot-spl-hawk.lds b/board/davinci/da8xxevm/u-boot-spl-hawk.lds
index 596a9e0..b452f20 100644
--- a/board/davinci/da8xxevm/u-boot-spl-hawk.lds
+++ b/board/davinci/da8xxevm/u-boot-spl-hawk.lds
@@ -61,7 +61,6 @@
 	__image_copy_end = .;
 	__rel_dyn_start = .;
 	__rel_dyn_end = .;
-	__dynsym_start = .;
 
 	__got_start = .;
 	. = ALIGN(4);
diff --git a/board/dvlhost/u-boot.lds b/board/dvlhost/u-boot.lds
index 6d4b187..f359112 100644
--- a/board/dvlhost/u-boot.lds
+++ b/board/dvlhost/u-boot.lds
@@ -30,6 +30,7 @@
 
 	. = ALIGN (4);
 	.text : {
+		*(.__image_copy_start)
 		arch/arm/cpu/ixp/start.o(.text*)
 		net/libnet.o(.text*)
 		board/dvlhost/libdvlhost.o(.text*)
@@ -62,17 +63,23 @@
 
 	. = ALIGN (4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -96,6 +103,7 @@
 		KEEP(*(.__bss_end));
 	}
 
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynamic*) }
 	/DISCARD/ : { *(.plt*) }
diff --git a/board/eltec/elppc/misc.c b/board/eltec/elppc/misc.c
index 89f1b1d..4c3656e 100644
--- a/board/eltec/elppc/misc.c
+++ b/board/eltec/elppc/misc.c
@@ -207,9 +207,14 @@
 		buf[4] = eerev.etheraddr[5];
 		buf[5] = eerev.etheraddr[4];
 
-		*(unsigned short *) &buf[20] = 0x48B2;
-		*(unsigned short *) &buf[22] = 0x0004;
-		*(unsigned short *) &buf[24] = 0x1433;
+		buf[20] = 0x48;
+		buf[21] = 0xB2;
+
+		buf[22] = 0x00;
+		buf[23] = 0x04;
+
+		buf[24] = 0x14;
+		buf[25] = 0x33;
 
 		printf ("\nSRom:  Writing i82559 info ........ ");
 		if (eepro100_srom_store ((unsigned short *) buf) == -1)
diff --git a/board/freescale/b4860qds/tlb.c b/board/freescale/b4860qds/tlb.c
index 29cc41b..1416f98 100644
--- a/board/freescale/b4860qds/tlb.c
+++ b/board/freescale/b4860qds/tlb.c
@@ -52,6 +52,15 @@
 	SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 0, BOOKE_PAGESZ_1M, 1),
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+	/*
+	 * SRIO_PCIE_BOOT-SLAVE. When slave boot, the address of the
+	 * space is at 0xfff00000, it covered the 0xfffff000.
+	 */
+	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR,
+		      CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
+		      0, 0, BOOKE_PAGESZ_1M, 1),
 #else
 	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -137,6 +146,16 @@
 		MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 16, BOOKE_PAGESZ_256M, 1),
 #endif
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+	/*
+	 * SRIO_PCIE_BOOT-SLAVE. 1M space from 0xffe00000 for
+	 * fetching ucode and ENV from master
+	 */
+	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR,
+		      CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
+		      0, 17, BOOKE_PAGESZ_1M, 1),
+#endif
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/board/freescale/bsc9131rdb/Makefile b/board/freescale/bsc9131rdb/Makefile
index 6f4cb26..2e829ad 100644
--- a/board/freescale/bsc9131rdb/Makefile
+++ b/board/freescale/bsc9131rdb/Makefile
@@ -24,12 +24,28 @@
 
 LIB    = $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y	+= spl_minimal.o tlb.o law.o
+
+else
+
 COBJS-y        += $(BOARD).o
 COBJS-y        += ddr.o
 COBJS-y        += law.o
 COBJS-y        += tlb.o
 #COBJS-y		+= bsc9131rdb_mux.o
 
+endif
+
 SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
 SOBJS  := $(addprefix $(obj),$(SOBJS))
diff --git a/board/freescale/bsc9131rdb/README b/board/freescale/bsc9131rdb/README
index 065faa3..4902b98 100644
--- a/board/freescale/bsc9131rdb/README
+++ b/board/freescale/bsc9131rdb/README
@@ -89,10 +89,14 @@
 Building U-boot
 --------------
 To build the u-boot for BSC9131RDB:
-1. NAND Flash
+1. NAND Flash with sysclk 66MHz(J16 on RDB closed, default)
 	make BSC9131RDB_NAND
-2. SPI Flash
+2. NAND Flash with sysclk 100MHz(J16 on RDB open)
+	make BSC9131RDB_NAND_SYSCLK100
+3. SPI Flash with sysclk 66MHz(J16 on RDB closed, default)
 	make BSC9131RDB_SPIFLASH
+4. SPI Flash with sysclk 100MHz(J16 on RDB open)
+	make BSC9131RDB_SPIFLASH_SYSCLK100
 
 Memory map
 -----------
@@ -107,6 +111,16 @@
  0xFF70_0000	0xFF7F_FFFF	PA CCSR			1M
  0xFF80_0000	0xFFFF_FFFF	Boot Page & NAND Buffer 8M
 
+DDR Memory map
+---------------
+ 0x0000_0000	0x36FF_FFFF	Memory passed onto Linux
+ 0x3700_0000	0x37FF_FFFF	PowerPC-DSP shared control area
+ 0x3800_0000	0x4FFF_FFFF	DSP Private area
+
+ Out of 880M, passed onto Linux, 1hugetlb page of 256M is reserved for
+ data communcation between PowerPC and DSP core.
+ Rest is PowerPC private area.
+
 Flashing Images
 ---------------
 To place a new u-boot image in the NAND flash and then boot
diff --git a/board/freescale/bsc9131rdb/law.c b/board/freescale/bsc9131rdb/law.c
index 201c147..0432780 100644
--- a/board/freescale/bsc9131rdb/law.c
+++ b/board/freescale/bsc9131rdb/law.c
@@ -26,6 +26,10 @@
 
 struct law_entry law_table[] = {
 	SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_IFC),
+	SET_LAW(CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS, LAW_SIZE_1M,
+		LAW_TRGT_IF_DSP_CCSR),
+	SET_LAW(CONFIG_SYS_FSL_DSP_M2_RAM_ADDR, LAW_SIZE_16M,
+		LAW_TRGT_IF_OCN_DSP),
 };
 
 int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/bsc9131rdb/spl_minimal.c b/board/freescale/bsc9131rdb/spl_minimal.c
new file mode 100644
index 0000000..301115e
--- /dev/null
+++ b/board/freescale/bsc9131rdb/spl_minimal.c
@@ -0,0 +1,118 @@
+/*
+ * 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 <asm/io.h>
+#include <nand.h>
+#include <linux/compiler.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Fixed sdram init -- doesn't use serial presence detect.
+ */
+static void sdram_init(void)
+{
+	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_800, &ddr->timing_cfg_3);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_0_800, &ddr->timing_cfg_0);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_1_800, &ddr->timing_cfg_1);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_2_800, &ddr->timing_cfg_2);
+
+	__raw_writel(CONFIG_SYS_DDR_CONTROL_2, &ddr->sdram_cfg_2);
+	__raw_writel(CONFIG_SYS_DDR_MODE_1_800, &ddr->sdram_mode);
+	__raw_writel(CONFIG_SYS_DDR_MODE_2_800, &ddr->sdram_mode_2);
+
+	__raw_writel(CONFIG_SYS_DDR_INTERVAL_800, &ddr->sdram_interval);
+	__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+	__raw_writel(CONFIG_SYS_DDR_CLK_CTRL_800, &ddr->sdram_clk_cntl);
+
+	__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_800, &ddr->ddr_wrlvl_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);
+
+	/* Set, but do not enable the memory */
+	__raw_writel(CONFIG_SYS_DDR_CONTROL & ~SDRAM_CFG_MEM_EN, &ddr->sdram_cfg);
+
+	asm volatile("sync;isync");
+	udelay(500);
+
+	/* Let the controller go */
+	out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
+
+	set_next_law(CONFIG_SYS_NAND_DDR_LAW, LAW_SIZE_1G, LAW_TRGT_IF_DDR_1);
+}
+
+void board_init_f(ulong bootflag)
+{
+	u32 plat_ratio;
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* initialize selected port with appropriate baud rate */
+	plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
+	plat_ratio >>= 1;
+	gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
+
+	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+		     gd->bus_clk / 16 / CONFIG_BAUDRATE);
+
+	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);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+	nand_boot();
+}
+
+void putc(char c)
+{
+	if (c == '\n')
+		NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
+
+	NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
+}
+
+void puts(const char *str)
+{
+	while (*str)
+		putc(*str++);
+}
diff --git a/board/freescale/bsc9131rdb/tlb.c b/board/freescale/bsc9131rdb/tlb.c
index 5b68f4a..c05a556 100644
--- a/board/freescale/bsc9131rdb/tlb.c
+++ b/board/freescale/bsc9131rdb/tlb.c
@@ -44,15 +44,26 @@
 	/* TLB 1 */
 	/* *I*** - Covers boot page */
 	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-			0, 0, BOOKE_PAGESZ_4K, 1),
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 0, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SPL_NAND_MINIMAL
+	SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 10, BOOKE_PAGESZ_4K, 1),
+#endif
 
 	/* *I*G* - CCSRBAR (PA) */
 	SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 1, BOOKE_PAGESZ_1M, 1),
 
-#if defined(CONFIG_SYS_RAMBOOT)
+	/* CCSRBAR (DSP) */
+	SET_TLB_ENTRY(1, CONFIG_SYS_FSL_DSP_CCSRBAR,
+		      CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 2, BOOKE_PAGESZ_1M, 1),
+
+#if  defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
 	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
 			MAS3_SX|MAS3_SW|MAS3_SR, 0,
 			0, 8, BOOKE_PAGESZ_1G, 1),
diff --git a/board/freescale/bsc9132qds/Makefile b/board/freescale/bsc9132qds/Makefile
index 267400b..72b1917 100644
--- a/board/freescale/bsc9132qds/Makefile
+++ b/board/freescale/bsc9132qds/Makefile
@@ -24,11 +24,28 @@
 
 LIB	= $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y	+= spl_minimal.o tlb.o law.o
+
+else
+
+
 COBJS-y	+= $(BOARD).o
 COBJS-y	+= ddr.o
 COBJS-y	+= law.o
 COBJS-y	+= tlb.o
 
+endif
+
 SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
diff --git a/board/freescale/bsc9132qds/bsc9132qds.c b/board/freescale/bsc9132qds/bsc9132qds.c
index 6e1b558..ddc9d0a 100644
--- a/board/freescale/bsc9132qds/bsc9132qds.c
+++ b/board/freescale/bsc9132qds/bsc9132qds.c
@@ -258,7 +258,7 @@
 	u8 val;
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 	u32 porbmsr = in_be32(&gur->porbmsr);
-	u32 romloc = (porbmsr >> MPC85XX_PORBMSR_ROMLOC_SHIFT) & 0xf;
+	u32 romloc = (porbmsr >> MPC85xx_PORBMSR_ROMLOC_SHIFT) & 0xf;
 
 	/*Configure 1588 clock-in source from RF Card*/
 	val = QIXIS_READ_I2C(brdcfg[5]);
@@ -360,7 +360,7 @@
 
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 	u32 porbmsr = in_be32(&gur->porbmsr);
-	u32 romloc = (porbmsr >> MPC85XX_PORBMSR_ROMLOC_SHIFT) & 0xf;
+	u32 romloc = (porbmsr >> MPC85xx_PORBMSR_ROMLOC_SHIFT) & 0xf;
 
 	if (!(hwconfig("uart2") && hwconfig("usb1"))) {
 		/* If uart2 is there in hwconfig remove usb node from
diff --git a/board/freescale/bsc9132qds/law.c b/board/freescale/bsc9132qds/law.c
index dc23658..b4bce99 100644
--- a/board/freescale/bsc9132qds/law.c
+++ b/board/freescale/bsc9132qds/law.c
@@ -25,11 +25,13 @@
 #include <asm/mmu.h>
 
 struct law_entry law_table[] = {
-#ifndef CONFIG_SYS_NO_FLASH
 	SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_128M, LAW_TRGT_IF_IFC),
-#endif
+#ifdef CONFIG_SYS_NAND_BASE_PHYS
 	SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_IFC),
+#endif
+#ifdef CONFIG_SYS_FPGA_BASE_PHYS
 	SET_LAW(CONFIG_SYS_FPGA_BASE_PHYS, LAW_SIZE_128K, LAW_TRGT_IF_IFC),
+#endif
 };
 
 int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/bsc9132qds/spl_minimal.c b/board/freescale/bsc9132qds/spl_minimal.c
new file mode 100644
index 0000000..62dee52
--- /dev/null
+++ b/board/freescale/bsc9132qds/spl_minimal.c
@@ -0,0 +1,130 @@
+/*
+ * 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 <asm/io.h>
+#include <nand.h>
+#include <linux/compiler.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void sdram_init(void)
+{
+	ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+#if CONFIG_DDR_CLK_FREQ == 100000000
+	__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
+	__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
+	__raw_writel(CONFIG_SYS_DDR_CONTROL_800 | SDRAM_CFG_32_BE, &ddr->sdram_cfg);
+	__raw_writel(CONFIG_SYS_DDR_CONTROL_2_800, &ddr->sdram_cfg_2);
+	__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+
+	__raw_writel(CONFIG_SYS_DDR_TIMING_3_800, &ddr->timing_cfg_3);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_0_800, &ddr->timing_cfg_0);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_1_800, &ddr->timing_cfg_1);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_2_800, &ddr->timing_cfg_2);
+	__raw_writel(CONFIG_SYS_DDR_MODE_1_800, &ddr->sdram_mode);
+	__raw_writel(CONFIG_SYS_DDR_MODE_2_800, &ddr->sdram_mode_2);
+	__raw_writel(CONFIG_SYS_DDR_INTERVAL_800, &ddr->sdram_interval);
+	__raw_writel(CONFIG_SYS_DDR_CLK_CTRL_800, &ddr->sdram_clk_cntl);
+	__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_800, &ddr->ddr_wrlvl_cntl);
+
+	__raw_writel(CONFIG_SYS_DDR_TIMING_4_800, &ddr->timing_cfg_4);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_5_800, &ddr->timing_cfg_5);
+	__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
+#elif CONFIG_DDR_CLK_FREQ == 133000000
+	__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
+	__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
+	__raw_writel(CONFIG_SYS_DDR_CONTROL_1333 | SDRAM_CFG_32_BE, &ddr->sdram_cfg);
+	__raw_writel(CONFIG_SYS_DDR_CONTROL_2_1333, &ddr->sdram_cfg_2);
+	__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+
+	__raw_writel(CONFIG_SYS_DDR_TIMING_3_1333, &ddr->timing_cfg_3);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_0_1333, &ddr->timing_cfg_0);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_1_1333, &ddr->timing_cfg_1);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_2_1333, &ddr->timing_cfg_2);
+	__raw_writel(CONFIG_SYS_DDR_MODE_1_1333, &ddr->sdram_mode);
+	__raw_writel(CONFIG_SYS_DDR_MODE_2_1333, &ddr->sdram_mode_2);
+	__raw_writel(CONFIG_SYS_DDR_INTERVAL_1333, &ddr->sdram_interval);
+	__raw_writel(CONFIG_SYS_DDR_CLK_CTRL_1333, &ddr->sdram_clk_cntl);
+	__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_1333, &ddr->ddr_wrlvl_cntl);
+
+	__raw_writel(CONFIG_SYS_DDR_TIMING_4_1333, &ddr->timing_cfg_4);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_5_1333, &ddr->timing_cfg_5);
+	__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
+#else
+	puts("Not a valid DDR Freq Found! Please Reset\n");
+#endif
+	asm volatile("sync;isync");
+	udelay(500);
+
+	/* Let the controller go */
+	out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
+
+	set_next_law(CONFIG_SYS_NAND_DDR_LAW, LAW_SIZE_1G, LAW_TRGT_IF_DDR_1);
+}
+
+void board_init_f(ulong bootflag)
+{
+	u32 plat_ratio;
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* initialize selected port with appropriate baud rate */
+	plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
+	plat_ratio >>= 1;
+	gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
+
+	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+		     gd->bus_clk / 16 / CONFIG_BAUDRATE);
+
+	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);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+	nand_boot();
+}
+
+void putc(char c)
+{
+	if (c == '\n')
+		NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
+
+	NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
+}
+
+void puts(const char *str)
+{
+	while (*str)
+		putc(*str++);
+}
diff --git a/board/freescale/bsc9132qds/tlb.c b/board/freescale/bsc9132qds/tlb.c
index 0e4545f..0ec9a85 100644
--- a/board/freescale/bsc9132qds/tlb.c
+++ b/board/freescale/bsc9132qds/tlb.c
@@ -44,14 +44,20 @@
 	/* TLB 1 */
 	/* *I*** - Covers boot page */
 	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-			0, 0, BOOKE_PAGESZ_4K, 1),
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 0, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SPL_NAND_MINIMAL
+	SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 10, BOOKE_PAGESZ_4K, 1),
+#endif
 
 	/* *I*G* - CCSRBAR (PA) */
 	SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 1, BOOKE_PAGESZ_1M, 1),
 
+#ifndef CONFIG_SPL_BUILD
 	SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
 			MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
 			0, 3, BOOKE_PAGESZ_64M, 1),
@@ -61,12 +67,6 @@
 			MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
 			0, 4, BOOKE_PAGESZ_64M, 1),
 
-#if defined(CONFIG_SYS_RAMBOOT)
-	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
-			MAS3_SX|MAS3_SW|MAS3_SR, 0,
-			0, 8, BOOKE_PAGESZ_1G, 1),
-#endif
-
 #ifdef CONFIG_PCI
 	/* *I*G* - PCI */
 	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
@@ -78,15 +78,26 @@
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 7, BOOKE_PAGESZ_64K, 1),
 #endif
+#endif
 
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
+	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 8, BOOKE_PAGESZ_1G, 1),
+#endif
+
+#ifdef CONFIG_SYS_FPGA_BASE
 		/* *I*G - Board FPGA  */
 	SET_TLB_ENTRY(1, CONFIG_SYS_FPGA_BASE, CONFIG_SYS_FPGA_BASE_PHYS,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 9, BOOKE_PAGESZ_256K, 1),
+#endif
 
+#ifdef CONFIG_SYS_NAND_BASE_PHYS
 	SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 5, BOOKE_PAGESZ_1M, 1),
+#endif
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile
index 72bb56c..37236d0 100644
--- a/board/freescale/common/Makefile
+++ b/board/freescale/common/Makefile
@@ -29,6 +29,15 @@
 
 LIB	= $(obj)libfreescale.o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifndef MINIMAL
 COBJS-$(CONFIG_FSL_CADMUS)	+= cadmus.o
 COBJS-$(CONFIG_FSL_VIA)		+= cds_via.o
 COBJS-$(CONFIG_FMAN_ENET)	+= fman.o
@@ -68,6 +77,7 @@
 SUBLIB-$(CONFIG_P4080DS)	+= p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P5020DS)	+= p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P5040DS)	+= p_corenet/libp_corenet.o
+endif
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/board/freescale/common/pixis.c b/board/freescale/common/pixis.c
index 8d07061..fbb709d 100644
--- a/board/freescale/common/pixis.c
+++ b/board/freescale/common/pixis.c
@@ -480,6 +480,7 @@
 	    ||	unknown_param) {
 #ifdef CONFIG_SYS_LONGHELP
 		puts(cmdtp->help);
+		putc('\n');
 #endif
 		return 1;
 	}
@@ -512,6 +513,7 @@
 		      && set_px_mpxpll(mpxpll))) {
 #ifdef CONFIG_SYS_LONGHELP
 			puts(cmdtp->help);
+			putc('\n');
 #endif
 			return 1;
 		}
diff --git a/board/freescale/mx31ads/u-boot.lds b/board/freescale/mx31ads/u-boot.lds
index 4969960..963d29f 100644
--- a/board/freescale/mx31ads/u-boot.lds
+++ b/board/freescale/mx31ads/u-boot.lds
@@ -34,6 +34,7 @@
 	. = ALIGN(4);
 	.text	   :
 	{
+		*(.__image_copy_start)
 	  /* WARNING - the following is hand-optimized to fit within	*/
 	  /* the sector layout of our flash chips!	XXX FIXME XXX	*/
 
@@ -65,17 +66,23 @@
 
 	. = ALIGN(4);
 
-	__image_copy_end = .;
-
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rel.dyn : {
+		*(.rel*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
 	}
 
 	_end = .;
@@ -100,6 +107,7 @@
 	}
 
 	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynsym*) }
 	/DISCARD/ : { *(.dynamic*) }
diff --git a/board/freescale/p1010rdb/Makefile b/board/freescale/p1010rdb/Makefile
index 4c705b6..e6563be 100644
--- a/board/freescale/p1010rdb/Makefile
+++ b/board/freescale/p1010rdb/Makefile
@@ -24,11 +24,27 @@
 
 LIB	= $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y	+= spl_minimal.o tlb.o law.o
+
+else
+
 COBJS-y	+= $(BOARD).o
 COBJS-y	+= ddr.o
 COBJS-y	+= law.o
 COBJS-y	+= tlb.o
 
+endif
+
 SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
 SOBJS	:= $(addprefix $(obj),$(SOBJS))
diff --git a/nand_spl/board/freescale/p1010rdb/nand_boot.c b/board/freescale/p1010rdb/spl_minimal.c
similarity index 94%
rename from nand_spl/board/freescale/p1010rdb/nand_boot.c
rename to board/freescale/p1010rdb/spl_minimal.c
index 3c7bc2b..c909e0e 100644
--- a/nand_spl/board/freescale/p1010rdb/nand_boot.c
+++ b/board/freescale/p1010rdb/spl_minimal.c
@@ -31,11 +31,18 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-unsigned long ddr_freq_mhz;
 
 void sdram_init(void)
 {
 	ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+	u32 ddr_ratio;
+	unsigned long ddr_freq_mhz;
+
+	ddr_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO;
+	ddr_ratio = ddr_ratio >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+	ddr_freq_mhz = (CONFIG_SYS_CLK_FREQ * ddr_ratio) / 0x1000000;
+
 	/* mask off E bit */
 	u32 svr = SVR_SOC_VER(mfspr(SPRN_SVR));
 
@@ -81,6 +88,7 @@
 		__raw_writel((CONFIG_SYS_DDR_CS0_BNDS >> 1) & 0x0fff0fff, &ddr->cs0_bnds);
 	}
 
+	asm volatile("sync;isync");
 	udelay(500);
 
 	/* Let the controller go */
@@ -91,7 +99,7 @@
 
 void board_init_f(ulong bootflag)
 {
-	u32 plat_ratio, ddr_ratio;
+	u32 plat_ratio;
 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
 
 	/* initialize selected port with appropriate baud rate */
@@ -99,10 +107,6 @@
 	plat_ratio >>= 1;
 	gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
 
-	ddr_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO;
-	ddr_ratio = ddr_ratio >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
-	ddr_freq_mhz = (CONFIG_SYS_CLK_FREQ * ddr_ratio) / 0x1000000;
-
 	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
 			gd->bus_clk / 16 / CONFIG_BAUDRATE);
 
@@ -115,8 +119,8 @@
 	/* NOTE - code has to be copied out of NAND buffer before
 	 * other blocks can be read.
 	 */
-	relocate_code(CONFIG_SYS_NAND_U_BOOT_RELOC_SP, 0,
-			CONFIG_SYS_NAND_U_BOOT_RELOC);
+
+	relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
 }
 
 void board_init_r(gd_t *gd, ulong dest_addr)
diff --git a/board/freescale/p1010rdb/tlb.c b/board/freescale/p1010rdb/tlb.c
index 4256bf4..078717a 100644
--- a/board/freescale/p1010rdb/tlb.c
+++ b/board/freescale/p1010rdb/tlb.c
@@ -44,15 +44,20 @@
 	/* TLB 1 */
 	/* *I*** - Covers boot page */
 	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-			0, 0, BOOKE_PAGESZ_4K, 1),
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 0, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SPL_NAND_MINIMAL
+	SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 10, BOOKE_PAGESZ_4K, 1),
+#endif
 
 	/* *I*G* - CCSRBAR */
 	SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
 			MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 1, BOOKE_PAGESZ_1M, 1),
 
-#ifndef CONFIG_NAND_SPL
+#ifndef CONFIG_SPL_BUILD
 #ifndef CONFIG_SDCARD
 	SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
 			MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
@@ -88,7 +93,7 @@
 			0, 7, BOOKE_PAGESZ_1M, 1),
 #endif
 
-#if defined(CONFIG_SYS_RAMBOOT)
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
 	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
 			MAS3_SX|MAS3_SW|MAS3_SR, 0,
 			0, 8, BOOKE_PAGESZ_1G, 1)
diff --git a/board/freescale/p1023rdb/Makefile b/board/freescale/p1023rdb/Makefile
new file mode 100644
index 0000000..45c4f8b
--- /dev/null
+++ b/board/freescale/p1023rdb/Makefile
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS-y	+= $(BOARD).o
+COBJS-y	+= ddr.o
+COBJS-y	+= law.o
+COBJS-y	+= tlb.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/freescale/p1023rdb/ddr.c b/board/freescale/p1023rdb/ddr.c
new file mode 100644
index 0000000..7ed275a
--- /dev/null
+++ b/board/freescale/p1023rdb/ddr.c
@@ -0,0 +1,105 @@
+/*
+ * 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 <common.h>
+#include <asm/mmu.h>
+#include <asm/immap_85xx.h>
+#include <asm/processor.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include <asm/io.h>
+#include <asm/fsl_law.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* CONFIG_SYS_DDR_RAW_TIMING */
+/*
+ * Hynix H5TQ1G83TFR-H9C
+ */
+dimm_params_t ddr_raw_timing = {
+	.n_ranks = 1,
+	.rank_density = 536870912u,
+	.capacity = 536870912u,
+	.primary_sdram_width = 32,
+	.ec_sdram_width = 0,
+	.registered_dimm = 0,
+	.mirrored_dimm = 0,
+	.n_row_addr = 14,
+	.n_col_addr = 10,
+	.n_banks_per_sdram_device = 8,
+	.edc_config = 0,
+	.burst_lengths_bitmask = 0x0c,
+
+	.tCKmin_X_ps = 1875,
+	.caslat_X = 0x1e << 4,	/* 5,6,7,8 */
+	.tAA_ps = 13125,
+	.tWR_ps = 18000,
+	.tRCD_ps = 13125,
+	.tRRD_ps = 7500,
+	.tRP_ps = 13125,
+	.tRAS_ps = 37500,
+	.tRC_ps = 50625,
+	.tRFC_ps = 160000,
+	.tWTR_ps = 7500,
+	.tRTP_ps = 7500,
+	.refresh_rate_ps = 7800000,
+	.tFAW_ps = 37500,
+};
+
+int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
+		unsigned int controller_number,
+		unsigned int dimm_number)
+{
+	const char dimm_model[] = "Fixed DDR on board";
+
+	if ((controller_number == 0) && (dimm_number == 0)) {
+		memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
+		memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+		memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+	}
+
+	return 0;
+}
+
+void fsl_ddr_board_options(memctl_options_t *popts,
+				dimm_params_t *pdimm,
+				unsigned int ctrl_num)
+{
+	int i;
+	popts->clk_adjust = 6;
+	popts->cpo_override = 0x1f;
+	popts->write_data_delay = 2;
+	popts->half_strength_driver_enable = 1;
+	/* Write leveling override */
+	popts->wrlvl_en = 1;
+	popts->wrlvl_override = 1;
+	popts->wrlvl_sample = 0xf;
+	popts->wrlvl_start = 0x8;
+	popts->trwt_override = 1;
+	popts->trwt = 0;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
+		popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
+	}
+}
+
diff --git a/board/freescale/p1023rdb/law.c b/board/freescale/p1023rdb/law.c
new file mode 100644
index 0000000..331662c
--- /dev/null
+++ b/board/freescale/p1023rdb/law.c
@@ -0,0 +1,34 @@
+/*
+ * 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 <common.h>
+#include <asm/fsl_law.h>
+#include <asm/mmu.h>
+
+struct law_entry law_table[] = {
+	SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
+	SET_LAW(CONFIG_SYS_QMAN_MEM_PHYS, LAW_SIZE_4M,
+		LAW_TRGT_IF_DPAA_SWP_SRAM),
+	SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/p1023rdb/p1023rdb.c b/board/freescale/p1023rdb/p1023rdb.c
new file mode 100644
index 0000000..918398b
--- /dev/null
+++ b/board/freescale/p1023rdb/p1023rdb.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Authors:  Roy Zang <tie-fei.zang@freescale.com>
+ *           Chunhe Lan <Chunhe.Lan@freescale.com>
+ *
+ * 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 <command.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/cache.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_pci.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_portals.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <netdev.h>
+#include <malloc.h>
+#include <fm_eth.h>
+#include <fsl_mdio.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/fsl_dtsec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+	fsl_lbc_t *lbc = LBC_BASE_ADDR;
+
+	/* Set ABSWP to implement conversion of addresses in the LBC */
+	setbits_be32(&lbc->lbcr, CONFIG_SYS_LBC_LBCR);
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	printf("Board: P1023 RDB\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+void pci_init_board(void)
+{
+	fsl_pcie_init_board(0);
+}
+#endif
+
+int board_early_init_r(void)
+{
+	const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
+	const u8 flash_esel = find_tlb_idx((void *)flashbase, 1);
+
+	/*
+	 * Remap Boot flash + PROMJET region to caching-inhibited
+	 * so that flash can be erased properly.
+	 */
+
+	/* Flush d-cache and invalidate i-cache of any FLASH data */
+	flush_dcache();
+	invalidate_icache();
+
+	/* invalidate existing TLB entry for flash + promjet */
+	disable_tlb(flash_esel);
+
+	set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
+		MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		0, flash_esel, BOOKE_PAGESZ_256M, 1);
+
+	setup_portals();
+
+	return 0;
+}
+
+unsigned long get_board_sys_clk(ulong dummy)
+{
+	return gd->bus_clk;
+}
+
+unsigned long get_board_ddr_clk(ulong dummy)
+{
+	return gd->mem_clk;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	ccsr_gur_t *gur = (ccsr_gur_t *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+	struct fsl_pq_mdio_info dtsec_mdio_info;
+
+	/*
+	 * Need to set dTSEC 1 pin multiplexing to TSEC. The default setting
+	 * is not correct.
+	 */
+	setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_TSEC1_1);
+
+	dtsec_mdio_info.regs =
+		(struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
+	dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
+
+	/* Register the 1G MDIO bus */
+	fsl_pq_mdio_init(bis, &dtsec_mdio_info);
+
+	fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
+	fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
+
+	fm_info_set_mdio(FM1_DTSEC1,
+			 miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
+	fm_info_set_mdio(FM1_DTSEC2,
+			 miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
+
+#ifdef CONFIG_FMAN_ENET
+	cpu_eth_init(bis);
+#endif
+
+	return pci_eth_init(bis);
+}
+
+#if defined(CONFIG_OF_BOARD_SETUP)
+void ft_board_setup(void *blob, bd_t *bd)
+{
+	phys_addr_t base;
+	phys_size_t size;
+
+	ft_cpu_setup(blob, bd);
+
+	base = getenv_bootm_low();
+	size = getenv_bootm_size();
+
+	fdt_fixup_memory(blob, (u64)base, (u64)size);
+
+#ifdef CONFIG_HAS_FSL_DR_USB
+	fdt_fixup_dr_usb(blob, bd);
+#endif
+
+	fdt_fixup_fman_ethernet(blob);
+}
+#endif
diff --git a/board/freescale/p1023rdb/tlb.c b/board/freescale/p1023rdb/tlb.c
new file mode 100644
index 0000000..3417c0f
--- /dev/null
+++ b/board/freescale/p1023rdb/tlb.c
@@ -0,0 +1,115 @@
+/*
+ * 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 <common.h>
+#include <asm/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+	/* TLB 0 - for temp stack in cache */
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR, CONFIG_SYS_INIT_RAM_ADDR,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
+		      CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
+		      CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+	SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
+		      CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 0, BOOKE_PAGESZ_4K, 0),
+
+	/* TLB 1 */
+	/* *I*** - Covers boot page */
+	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I,
+		      0, 0, BOOKE_PAGESZ_4K, 1),
+
+	/* *I*G* - CCSRBAR */
+	SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 1, BOOKE_PAGESZ_4M, 1),
+
+	/* W**G* - Flash, 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,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
+		      0, 2, BOOKE_PAGESZ_256M, 1),
+
+	/* *I*G* - PCI */
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_MEM_VIRT, CONFIG_SYS_PCIE3_MEM_PHYS,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 3, BOOKE_PAGESZ_1G, 1),
+
+	/* *I*G* - PCI */
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_MEM_VIRT + 0x40000000,
+		      CONFIG_SYS_PCIE3_MEM_PHYS + 0x40000000,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 4, BOOKE_PAGESZ_256M, 1),
+
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_MEM_VIRT + 0x50000000,
+		      CONFIG_SYS_PCIE3_MEM_PHYS + 0x50000000,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 5, BOOKE_PAGESZ_256M, 1),
+
+	/* *I*G* - PCI I/O */
+	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_IO_VIRT, CONFIG_SYS_PCIE3_IO_PHYS,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 6, BOOKE_PAGESZ_256K, 1),
+
+	/* Bman/Qman */
+	SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE, CONFIG_SYS_BMAN_MEM_PHYS,
+		      MAS3_SW|MAS3_SR, 0,
+		      0, 7, BOOKE_PAGESZ_1M, 1),
+	SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE + 0x00100000,
+		      CONFIG_SYS_BMAN_MEM_PHYS + 0x00100000,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 8, BOOKE_PAGESZ_1M, 1),
+	SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE, CONFIG_SYS_QMAN_MEM_PHYS,
+		      MAS3_SW|MAS3_SR, MAS2_M,
+		      0, 9, BOOKE_PAGESZ_1M, 1),
+	SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE + 0x00100000,
+		      CONFIG_SYS_QMAN_MEM_PHYS + 0x00100000,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 10, BOOKE_PAGESZ_1M, 1),
+
+	SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
+		      MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 11, BOOKE_PAGESZ_16K, 1),
+
+#ifdef CONFIG_SYS_RAMBOOT
+	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE,
+		      CONFIG_SYS_DDR_SDRAM_BASE,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 12, BOOKE_PAGESZ_256M, 1),
+
+	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000,
+		      CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000,
+		      MAS3_SX|MAS3_SW|MAS3_SR, 0,
+		      0, 13, BOOKE_PAGESZ_256M, 1),
+#endif
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/board/freescale/t4qds/tlb.c b/board/freescale/t4qds/tlb.c
index 92c01cf..a138d5a 100644
--- a/board/freescale/t4qds/tlb.c
+++ b/board/freescale/t4qds/tlb.c
@@ -55,6 +55,15 @@
 	SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 			0, 0, BOOKE_PAGESZ_1M, 1),
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+	/*
+	 * SRIO_PCIE_BOOT-SLAVE. When slave boot, the address of the
+	 * space is at 0xfff00000, it covered the 0xfffff000.
+	 */
+	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR,
+		      CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
+		      0, 0, BOOKE_PAGESZ_1M, 1),
 #else
 	SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -130,6 +139,16 @@
 	SET_TLB_ENTRY(1, QIXIS_BASE, QIXIS_BASE_PHYS,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 17, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+	/*
+	 * SRIO_PCIE_BOOT-SLAVE. 1M space from 0xffe00000 for
+	 * fetching ucode and ENV from master
+	 */
+	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR,
+		      CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
+		      0, 18, BOOKE_PAGESZ_1M, 1),
+#endif
 
 };
 
diff --git a/board/ifm/ac14xx/ac14xx.c b/board/ifm/ac14xx/ac14xx.c
index 7442591..dc2aff0 100644
--- a/board/ifm/ac14xx/ac14xx.c
+++ b/board/ifm/ac14xx/ac14xx.c
@@ -23,6 +23,10 @@
 #include <i2c.h>
 #endif
 
+static int eeprom_diag;
+static int mac_diag;
+static int gpio_diag;
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static void gpio_configure(void)
@@ -37,7 +41,7 @@
 
 	/*
 	 * out_be32(&gpioregs->gpdir, 0xC2293020);
-	 * workaround for a hardware affect: configure direction in pieces,
+	 * workaround for a hardware effect: configure direction in pieces,
 	 * setting all outputs at once drops the reset line too low and
 	 * makes us lose the MII connection (breaks ethernet for us)
 	 */
@@ -126,8 +130,6 @@
 
 /* excerpt from the recovery's hw_info.h */
 
-static int eeprom_diag = 1;
-
 struct __attribute__ ((__packed__)) eeprom_layout {
 	char	magic[3];	/** 'ifm' */
 	u8	len[2];		/** content length without magic/len fields */
@@ -209,6 +211,7 @@
 int mac_read_from_eeprom(void)
 {
 	const u8 *mac;
+	const char *mac_txt;
 
 	if (read_eeprom()) {
 		printf("I2C EEPROM read failed.\n");
@@ -230,8 +233,13 @@
 
 	if (mac && is_valid_ether_addr(mac)) {
 		eth_setenv_enetaddr("ethaddr", mac);
-		printf("DIAG: %s() MAC value [%s]\n",
-			__func__, getenv("ethaddr"));
+		if (mac_diag) {
+			mac_txt = getenv("ethaddr");
+			if (mac_txt)
+				printf("DIAG: MAC value [%s]\n", mac_txt);
+			else
+				printf("DIAG: failed to setup MAC env\n");
+		}
 	}
 
 	return 0;
@@ -326,42 +334,38 @@
 	gpio_configure();
 
 	/*
-	 * check the GPIO keyboard,
-	 * enforced start of the recovery when
+	 * enforce the start of the recovery system when
 	 * - the appropriate keys were pressed
-	 * - a previous installation was aborted or has failed
 	 * - "some" external software told us to
+	 * - a previous installation was aborted or has failed
 	 */
 	want_recovery = 0;
 	keys = gpio_querykbd();
-	printf("GPIO keyboard status [0x%08X]\n", keys);
-	/* XXX insist in the _exact_ combination? */
+	if (gpio_diag)
+		printf("GPIO keyboard status [0x%02X]\n", keys);
 	if ((keys & GPIOKEY_BITS_RECOVERY) == GPIOKEY_BITS_RECOVERY) {
-		printf("GPIO keyboard requested RECOVERY\n");
-		/* XXX TODO
-		 * refine the logic to detect the first keypress, and
-		 * wait to recheck IF it was the recovery combination?
-		 */
-		want_recovery = 1;
-	}
-	s = getenv("install_in_progress");
-	if ((s != NULL) && (*s != '\0')) {
-		printf("previous installation aborted, running RECOVERY\n");
-		want_recovery = 1;
-	}
-	s = getenv("install_failed");
-	if ((s != NULL) && (*s != '\0')) {
-		printf("previous installation FAILED, running RECOVERY\n");
+		printf("detected recovery request (keyboard)\n");
 		want_recovery = 1;
 	}
 	s = getenv("want_recovery");
 	if ((s != NULL) && (*s != '\0')) {
-		printf("running RECOVERY according to the request\n");
+		printf("detected recovery request (environment)\n");
 		want_recovery = 1;
 	}
-
-	if (want_recovery)
+	s = getenv("install_in_progress");
+	if ((s != NULL) && (*s != '\0')) {
+		printf("previous installation has not completed\n");
+		want_recovery = 1;
+	}
+	s = getenv("install_failed");
+	if ((s != NULL) && (*s != '\0')) {
+		printf("previous installation has failed\n");
+		want_recovery = 1;
+	}
+	if (want_recovery) {
+		printf("enforced start of the recovery system\n");
 		setenv("bootcmd", "run recovery");
+	}
 
 	/*
 	 * boot the recovery system without waiting; boot the
diff --git a/board/isee/igep0033/board.c b/board/isee/igep0033/board.c
index 826cead..ea3bea5 100644
--- a/board/isee/igep0033/board.c
+++ b/board/isee/igep0033/board.c
@@ -36,37 +36,13 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-#ifdef CONFIG_SPL_BUILD
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
-#endif
 
 /* MII mode defines */
 #define RMII_MODE_ENABLE	0x4D
 
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
 
-/* UART Defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET		(0x1 << 1)
-#define UART_CLK_RUNNING_MASK	0x1
-#define UART_SMART_IDLE_EN	(0x1 << 0x3)
-
-static void rtc32k_enable(void)
-{
-	struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-	/*
-	 * Unlock the RTC's registers.  For more details please see the
-	 * RTC_SS section of the TRM.  In order to unlock we need to
-	 * write these specific values (keys) in this order.
-	 */
-	writel(0x83e70b13, &rtc->kick0r);
-	writel(0x95a4f1e0, &rtc->kick1r);
-
-	/* Enable the RTC 32K OSC by setting bits 3 and 6. */
-	writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static const struct ddr_data ddr3_data = {
 	.datardsratio0 = K4B2G1646EBIH9_RD_DQS,
 	.datawdsratio0 = K4B2G1646EBIH9_WR_DQS,
@@ -131,23 +107,9 @@
 	/* Enable RTC32K clock */
 	rtc32k_enable();
 
-	/* UART softreset */
-	u32 regval;
-
 	enable_uart0_pin_mux();
 
-	regval = readl(&uart_base->uartsyscfg);
-	regval |= UART_RESET;
-	writel(regval, &uart_base->uartsyscfg);
-	while ((readl(&uart_base->uartsyssts) &
-		UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
-		;
-
-	/* Disable smart idle */
-	regval = readl(&uart_base->uartsyscfg);
-	regval |= UART_SMART_IDLE_EN;
-	writel(regval, &uart_base->uartsyscfg);
-
+	uart_soft_reset();
 	gd = &gdata;
 
 	preloader_console_init();
diff --git a/board/phytec/pcm051/board.c b/board/phytec/pcm051/board.c
index 93c611d..0cca8d7 100644
--- a/board/phytec/pcm051/board.c
+++ b/board/phytec/pcm051/board.c
@@ -39,9 +39,6 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-#ifdef CONFIG_SPL_BUILD
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
-#endif
 
 /* MII mode defines */
 #define MII_MODE_ENABLE		0x0
@@ -50,31 +47,11 @@
 
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
 
-/* UART defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET		(0x1 << 1)
-#define UART_CLK_RUNNING_MASK	0x1
-#define UART_SMART_IDLE_EN	(0x1 << 0x3)
 
 /* DDR RAM defines */
 #define DDR_CLK_MHZ		303 /* DDR_DPLL_MULT value */
 
-static void rtc32k_enable(void)
-{
-	struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-	/*
-	 * Unlock the RTC's registers.  For more details please see the
-	 * RTC_SS section of the TRM.  In order to unlock we need to
-	 * write these specific values (keys) in this order.
-	 */
-	writel(0x83e70b13, &rtc->kick0r);
-	writel(0x95a4f1e0, &rtc->kick1r);
-
-	/* Enable the RTC 32K OSC by setting bits 3 and 6. */
-	writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static const struct ddr_data ddr3_data = {
 	.datardsratio0 = MT41J256M8HX15E_RD_DQS,
 	.datawdsratio0 = MT41J256M8HX15E_WR_DQS,
@@ -141,22 +118,8 @@
 	/* Enable RTC32K clock */
 	rtc32k_enable();
 
-	/* UART softreset */
-	u32 regval;
-
 	enable_uart0_pin_mux();
-
-	regval = readl(&uart_base->uartsyscfg);
-	regval |= UART_RESET;
-	writel(regval, &uart_base->uartsyscfg);
-	while ((readl(&uart_base->uartsyssts) &	UART_CLK_RUNNING_MASK)
-		!= UART_CLK_RUNNING_MASK)
-		;
-
-	/* Disable smart idle */
-	regval = readl(&uart_base->uartsyscfg);
-	regval |= UART_SMART_IDLE_EN;
-	writel(regval, &uart_base->uartsyscfg);
+	uart_soft_reset();
 
 	gd = &gdata;
 
diff --git a/board/samsung/dts/exynos5250-smdk5250.dts b/board/samsung/dts/exynos5250-smdk5250.dts
index 8da973b..93375a6 100644
--- a/board/samsung/dts/exynos5250-smdk5250.dts
+++ b/board/samsung/dts/exynos5250-smdk5250.dts
@@ -30,6 +30,10 @@
 		spi2 = "/spi@12d40000";
 		spi3 = "/spi@131a0000";
 		spi4 = "/spi@131b0000";
+		mmc0 = "/mmc@12200000";
+		mmc1 = "/mmc@12210000";
+		mmc2 = "/mmc@12220000";
+		mmc3 = "/mmc@12230000";
 	};
 
 	sromc@12250000 {
@@ -119,4 +123,24 @@
 		samsung,ycbcr-coeff = <0>;
 		samsung,color-depth = <1>;
 	};
+
+	mmc@12200000 {
+		samsung,bus-width = <8>;
+		samsung,timing = <1 3 3>;
+		samsung,removable = <0>;
+	};
+
+	mmc@12210000 {
+		status = "disabled";
+	};
+
+	mmc@12220000 {
+		samsung,bus-width = <4>;
+		samsung,timing = <1 2 3>;
+		samsung,removable = <1>;
+	};
+
+	mmc@12230000 {
+		status = "disabled";
+	};
 };
diff --git a/board/samsung/dts/exynos5250-snow.dts b/board/samsung/dts/exynos5250-snow.dts
index 24658c1..d2ccc66 100644
--- a/board/samsung/dts/exynos5250-snow.dts
+++ b/board/samsung/dts/exynos5250-snow.dts
@@ -32,6 +32,33 @@
 		spi4 = "/spi@131b0000";
 	};
 
+	i2c4: i2c@12ca0000 {
+		cros-ec@1e {
+			reg = <0x1e>;
+			compatible = "google,cros-ec";
+			i2c-max-frequency = <100000>;
+			ec-interrupt = <&gpio 782 1>;
+		};
+
+		power-regulator@48 {
+			compatible = "ti,tps65090";
+			reg = <0x48>;
+		};
+	};
+
+	spi@131b0000 {
+		spi-max-frequency = <1000000>;
+		spi-deactivate-delay = <100>;
+		cros-ec@0 {
+			reg = <0>;
+			compatible = "google,cros-ec";
+			spi-max-frequency = <5000000>;
+			ec-interrupt = <&gpio 782 1>;
+			optimise-flash-write;
+			status = "disabled";
+		};
+	};
+
 	sound@12d60000 {
 		samsung,i2s-epll-clock-frequency = <192000000>;
 		samsung,i2s-sampling-rate = <48000>;
@@ -69,4 +96,58 @@
 		samsung,dc-value	= <25>;
 	};
 
+	cros-ec-keyb {
+		compatible = "google,cros-ec-keyb";
+		google,key-rows = <8>;
+		google,key-columns = <13>;
+		google,repeat-delay-ms = <240>;
+		google,repeat-rate-ms = <30>;
+		google,ghost-filter;
+		/*
+		 * Keymap entries take the form of 0xRRCCKKKK where
+		 * RR=Row CC=Column KKKK=Key Code
+		 * The values below are for a US keyboard layout and
+		 * are taken from the Linux driver. Note that the
+		 * 102ND key is not used for US keyboards.
+		 */
+		linux,keymap = <
+			/* CAPSLCK F1         B          F10     */
+			0x0001003a 0x0002003b 0x00030030 0x00040044
+			/* N       =          R_ALT      ESC     */
+			0x00060031 0x0008000d 0x000a0064 0x01010001
+			/* F4      G          F7         H       */
+			0x0102003e 0x01030022 0x01040041 0x01060023
+			/* '       F9         BKSPACE    L_CTRL  */
+			0x01080028 0x01090043 0x010b000e 0x0200001d
+			/* TAB     F3         T          F6      */
+			0x0201000f 0x0202003d 0x02030014 0x02040040
+			/* ]       Y          102ND      [       */
+			0x0205001b 0x02060015 0x02070056 0x0208001a
+			/* F8      GRAVE      F2         5       */
+			0x02090042 0x03010029 0x0302003c 0x03030006
+			/* F5      6          -          \       */
+			0x0304003f 0x03060007 0x0308000c 0x030b002b
+			/* R_CTRL  A          D          F       */
+			0x04000061 0x0401001e 0x04020020 0x04030021
+			/* S       K          J          ;       */
+			0x0404001f 0x04050025 0x04060024 0x04080027
+			/* L       ENTER      Z          C       */
+			0x04090026 0x040b001c 0x0501002c 0x0502002e
+			/* V       X          ,          M       */
+			0x0503002f 0x0504002d 0x05050033 0x05060032
+			/* L_SHIFT /          .          SPACE   */
+			0x0507002a 0x05080035 0x05090034 0x050B0039
+			/* 1       3          4          2       */
+			0x06010002 0x06020004 0x06030005 0x06040003
+			/* 8       7          0          9       */
+			0x06050009 0x06060008 0x0608000b 0x0609000a
+			/* L_ALT   DOWN       RIGHT      Q       */
+			0x060a0038 0x060b006c 0x060c006a 0x07010010
+			/* E       R          W          I       */
+			0x07020012 0x07030013 0x07040011 0x07050017
+			/* U       R_SHIFT    P          O       */
+			0x07060016 0x07070036 0x07080019 0x07090018
+			/* UP      LEFT    */
+			0x070b0067 0x070c0069>;
+	};
 };
diff --git a/board/samsung/origen/lowlevel_init.S b/board/samsung/origen/lowlevel_init.S
index 9daa0da..be9d418 100644
--- a/board/samsung/origen/lowlevel_init.S
+++ b/board/samsung/origen/lowlevel_init.S
@@ -87,12 +87,14 @@
 1:
 	/* for UART */
 	bl uart_asm_init
+	bl arch_cpu_init
 	bl tzpc_init
 	pop	{pc}
 
 wakeup_reset:
 	bl system_clock_init
 	bl mem_ctrl_asm_init
+	bl arch_cpu_init
 	bl tzpc_init
 
 exit_wakeup:
@@ -353,45 +355,3 @@
 	nop
 	nop
 
-/* Setting TZPC[TrustZone Protection Controller] */
-tzpc_init:
-	ldr	r0, =TZPC0_BASE
-	mov	r1, #R0SIZE
-	str	r1, [r0]
-	mov	r1, #DECPROTXSET
-	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-	ldr	r0, =TZPC1_BASE
-	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-	ldr	r0, =TZPC2_BASE
-	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-	ldr	r0, =TZPC3_BASE
-	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-	ldr	r0, =TZPC4_BASE
-	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-	ldr	r0, =TZPC5_BASE
-	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-	mov	pc, lr
diff --git a/board/samsung/origen/origen_setup.h b/board/samsung/origen/origen_setup.h
index 930b948..926a4cc 100644
--- a/board/samsung/origen/origen_setup.h
+++ b/board/samsung/origen/origen_setup.h
@@ -121,19 +121,6 @@
 #define UBRDIV_OFFSET		0x28
 #define UFRACVAL_OFFSET		0x2C
 
-/* TZPC : Register Offsets */
-#define TZPC0_BASE		0x10110000
-#define TZPC1_BASE		0x10120000
-#define TZPC2_BASE		0x10130000
-#define TZPC3_BASE		0x10140000
-#define TZPC4_BASE		0x10150000
-#define TZPC5_BASE		0x10160000
-
-#define TZPC_DECPROT0SET_OFFSET	0x804
-#define TZPC_DECPROT1SET_OFFSET	0x810
-#define TZPC_DECPROT2SET_OFFSET	0x81C
-#define TZPC_DECPROT3SET_OFFSET	0x828
-
 /* CLK_SRC_CPU */
 #define MUX_HPM_SEL_MOUTAPLL		0x0
 #define MUX_HPM_SEL_SCLKMPLL		0x1
@@ -617,16 +604,4 @@
  * UBRFRACVAL = ((((800MHz*10/(115200*16) -10))%10)*16/10)
  */
 #define UFRACVAL_VAL		0x4
-
-/*
- * TZPC Register Value :
- * R0SIZE: 0x0 : Size of secured ram
- */
-#define R0SIZE			0x0
-
-/*
- * TZPC Decode Protection Register Value :
- * DECPROTXSET: 0xFF : Set Decode region to non-secure
- */
-#define DECPROTXSET		0xFF
 #endif
diff --git a/board/samsung/smdk5250/Makefile b/board/samsung/smdk5250/Makefile
index 47c6a5a..f2c32ee 100644
--- a/board/samsung/smdk5250/Makefile
+++ b/board/samsung/smdk5250/Makefile
@@ -28,12 +28,15 @@
 
 COBJS	:= clock_init.o
 COBJS	+= dmc_common.o dmc_init_ddr3.o
-COBJS	+= tzpc_init.o
 COBJS	+= smdk5250_spl.o
 
 ifndef CONFIG_SPL_BUILD
+ifdef CONFIG_OF_CONTROL
+COBJS	+= exynos5-dt.o
+else
 COBJS	+= smdk5250.o
 endif
+endif
 
 ifdef CONFIG_SPL_BUILD
 COBJS	+= spl_boot.o
diff --git a/board/samsung/smdk5250/clock_init.c b/board/samsung/smdk5250/clock_init.c
index 5b9e82f..b288e66 100644
--- a/board/samsung/smdk5250/clock_init.c
+++ b/board/samsung/smdk5250/clock_init.c
@@ -28,10 +28,14 @@
 #include <asm/arch/clk.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/spl.h>
+#include <asm/arch/dwmmc.h>
 
 #include "clock_init.h"
 #include "setup.h"
 
+#define FSYS1_MMC0_DIV_MASK	0xff0f
+#define FSYS1_MMC0_DIV_VAL	0x0701
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct arm_clk_ratios arm_clk_ratios[] = {
@@ -664,3 +668,17 @@
 	/* We run DP at 267 Mhz */
 	setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
 }
+
+/*
+ * Set clock divisor value for booting from EMMC.
+ * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz.
+ */
+void emmc_boot_clk_div_set(void)
+{
+	struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+	unsigned int div_mmc;
+
+	div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK;
+	div_mmc |= FSYS1_MMC0_DIV_VAL;
+	writel(div_mmc, (unsigned int) &clk->div_fsys1);
+}
diff --git a/board/samsung/smdk5250/clock_init.h b/board/samsung/smdk5250/clock_init.h
index f751bcb..20a1d47 100644
--- a/board/samsung/smdk5250/clock_init.h
+++ b/board/samsung/smdk5250/clock_init.h
@@ -146,4 +146,9 @@
  * Initialize clock for the device
  */
 void system_clock_init(void);
+
+/*
+ * Set clock divisor value for booting from EMMC.
+ */
+void emmc_boot_clk_div_set(void);
 #endif
diff --git a/board/samsung/smdk5250/exynos5-dt.c b/board/samsung/smdk5250/exynos5-dt.c
new file mode 100644
index 0000000..aacf43e
--- /dev/null
+++ b/board/samsung/smdk5250/exynos5-dt.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * 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 <cros_ec.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <i2c.h>
+#include <netdev.h>
+#include <spi.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/dwmmc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/power.h>
+#include <asm/arch/sromc.h>
+#include <power/pmic.h>
+#include <power/max77686_pmic.h>
+#include <tmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined CONFIG_EXYNOS_TMU
+/*
+ * Boot Time Thermal Analysis for SoC temperature threshold breach
+ */
+static void boot_temp_check(void)
+{
+	int temp;
+
+	switch (tmu_monitor(&temp)) {
+	/* Status TRIPPED ans WARNING means corresponding threshold breach */
+	case TMU_STATUS_TRIPPED:
+		puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
+		set_ps_hold_ctrl();
+		hang();
+		break;
+	case TMU_STATUS_WARNING:
+		puts("EXYNOS_TMU: WARNING! Temperature very high\n");
+		break;
+	/*
+	 * TMU_STATUS_INIT means something is wrong with temperature sensing
+	 * and TMU status was changed back from NORMAL to INIT.
+	 */
+	case TMU_STATUS_INIT:
+	default:
+		debug("EXYNOS_TMU: Unknown TMU state\n");
+	}
+}
+#endif
+
+struct local_info {
+	struct cros_ec_dev *cros_ec_dev;	/* Pointer to cros_ec device */
+	int cros_ec_err;			/* Error for cros_ec, 0 if ok */
+};
+
+static struct local_info local;
+
+#ifdef CONFIG_USB_EHCI_EXYNOS
+int board_usb_vbus_init(void)
+{
+	struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
+						samsung_get_base_gpio_part1();
+
+	/* Enable VBUS power switch */
+	s5p_gpio_direction_output(&gpio1->x2, 6, 1);
+
+	/* VBUS turn ON time */
+	mdelay(3);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SOUND_MAX98095
+static void  board_enable_audio_codec(void)
+{
+	struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
+						samsung_get_base_gpio_part1();
+
+	/* Enable MAX98095 Codec */
+	s5p_gpio_direction_output(&gpio1->x1, 7, 1);
+	s5p_gpio_set_pull(&gpio1->x1, 7, GPIO_PULL_NONE);
+}
+#endif
+
+struct cros_ec_dev *board_get_cros_ec_dev(void)
+{
+	return local.cros_ec_dev;
+}
+
+static int board_init_cros_ec_devices(const void *blob)
+{
+	local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev);
+	if (local.cros_ec_err)
+		return -1;  /* Will report in board_late_init() */
+
+	return 0;
+}
+
+int board_init(void)
+{
+	gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
+
+#if defined CONFIG_EXYNOS_TMU
+	if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
+		debug("%s: Failed to init TMU\n", __func__);
+		return -1;
+	}
+	boot_temp_check();
+#endif
+
+#ifdef CONFIG_EXYNOS_SPI
+	spi_init();
+#endif
+
+	if (board_init_cros_ec_devices(gd->fdt_blob))
+		return -1;
+
+#ifdef CONFIG_USB_EHCI_EXYNOS
+	board_usb_vbus_init();
+#endif
+#ifdef CONFIG_SOUND_MAX98095
+	board_enable_audio_codec();
+#endif
+	return 0;
+}
+
+int dram_init(void)
+{
+	int i;
+	u32 addr;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+		gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+	}
+	return 0;
+}
+
+#if defined(CONFIG_POWER)
+static int pmic_reg_update(struct pmic *p, int reg, uint regval)
+{
+	u32 val;
+	int ret = 0;
+
+	ret = pmic_reg_read(p, reg, &val);
+	if (ret) {
+		debug("%s: PMIC %d register read failed\n", __func__, reg);
+		return -1;
+	}
+	val |= regval;
+	ret = pmic_reg_write(p, reg, val);
+	if (ret) {
+		debug("%s: PMIC %d register write failed\n", __func__, reg);
+		return -1;
+	}
+	return 0;
+}
+
+int power_init_board(void)
+{
+	struct pmic *p;
+
+	set_ps_hold_ctrl();
+
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	if (pmic_init(I2C_PMIC))
+		return -1;
+
+	p = pmic_get("MAX77686_PMIC");
+	if (!p)
+		return -ENODEV;
+
+	if (pmic_probe(p))
+		return -1;
+
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_32KHZ, MAX77686_32KHCP_EN))
+		return -1;
+
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_BBAT,
+			    MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V))
+		return -1;
+
+	/* VDD_MIF */
+	if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK1OUT,
+			   MAX77686_BUCK1OUT_1V)) {
+		debug("%s: PMIC %d register write failed\n", __func__,
+		      MAX77686_REG_PMIC_BUCK1OUT);
+		return -1;
+	}
+
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK1CRTL,
+			    MAX77686_BUCK1CTRL_EN))
+		return -1;
+
+	/* VDD_ARM */
+	if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1,
+			   MAX77686_BUCK2DVS1_1_3V)) {
+		debug("%s: PMIC %d register write failed\n", __func__,
+		      MAX77686_REG_PMIC_BUCK2DVS1);
+		return -1;
+	}
+
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK2CTRL1,
+			    MAX77686_BUCK2CTRL_ON))
+		return -1;
+
+	/* VDD_INT */
+	if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK3DVS1,
+			   MAX77686_BUCK3DVS1_1_0125V)) {
+		debug("%s: PMIC %d register write failed\n", __func__,
+		      MAX77686_REG_PMIC_BUCK3DVS1);
+		return -1;
+	}
+
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK3CTRL,
+			    MAX77686_BUCK3CTRL_ON))
+		return -1;
+
+	/* VDD_G3D */
+	if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK4DVS1,
+			   MAX77686_BUCK4DVS1_1_2V)) {
+		debug("%s: PMIC %d register write failed\n", __func__,
+		      MAX77686_REG_PMIC_BUCK4DVS1);
+		return -1;
+	}
+
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK4CTRL1,
+			    MAX77686_BUCK3CTRL_ON))
+		return -1;
+
+	/* VDD_LDO2 */
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO2CTRL1,
+			    MAX77686_LD02CTRL1_1_5V | EN_LDO))
+		return -1;
+
+	/* VDD_LDO3 */
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO3CTRL1,
+			    MAX77686_LD03CTRL1_1_8V | EN_LDO))
+		return -1;
+
+	/* VDD_LDO5 */
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO5CTRL1,
+			    MAX77686_LD05CTRL1_1_8V | EN_LDO))
+		return -1;
+
+	/* VDD_LDO10 */
+	if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO10CTRL1,
+			    MAX77686_LD10CTRL1_1_8V | EN_LDO))
+		return -1;
+
+	return 0;
+}
+#endif
+
+void dram_init_banksize(void)
+{
+	int i;
+	u32 addr, size;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+		size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+
+		gd->bd->bi_dram[i].start = addr;
+		gd->bd->bi_dram[i].size = size;
+	}
+}
+
+static int decode_sromc(const void *blob, struct fdt_sromc *config)
+{
+	int err;
+	int node;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
+	if (node < 0) {
+		debug("Could not find SROMC node\n");
+		return node;
+	}
+
+	config->bank = fdtdec_get_int(blob, node, "bank", 0);
+	config->width = fdtdec_get_int(blob, node, "width", 2);
+
+	err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
+			FDT_SROM_TIMING_COUNT);
+	if (err < 0) {
+		debug("Could not decode SROMC configuration Error: %s\n",
+		      fdt_strerror(err));
+		return -FDT_ERR_NOTFOUND;
+	}
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_SMC911X
+	u32 smc_bw_conf, smc_bc_conf;
+	struct fdt_sromc config;
+	fdt_addr_t base_addr;
+	int node;
+
+	node = decode_sromc(gd->fdt_blob, &config);
+	if (node < 0) {
+		debug("%s: Could not find sromc configuration\n", __func__);
+		return 0;
+	}
+	node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
+	if (node < 0) {
+		debug("%s: Could not find lan9215 configuration\n", __func__);
+		return 0;
+	}
+
+	/* We now have a node, so any problems from now on are errors */
+	base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
+	if (base_addr == FDT_ADDR_T_NONE) {
+		debug("%s: Could not find lan9215 address\n", __func__);
+		return -1;
+	}
+
+	/* Ethernet needs data bus width of 16 bits */
+	if (config.width != 2) {
+		debug("%s: Unsupported bus width %d\n", __func__,
+		      config.width);
+		return -1;
+	}
+	smc_bw_conf = SROMC_DATA16_WIDTH(config.bank)
+			| SROMC_BYTE_ENABLE(config.bank);
+
+	smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS])   |
+			SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |
+			SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |
+			SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |
+			SROMC_BC_TAH(config.timing[FDT_SROM_TAH])   |
+			SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |
+			SROMC_BC_PMC(config.timing[FDT_SROM_PMC]);
+
+	/* Select and configure the SROMC bank */
+	exynos_pinmux_config(PERIPH_ID_SROMC, config.bank);
+	s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf);
+	return smc911x_initialize(0, base_addr);
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+	const char *board_name;
+
+	board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+	if (board_name == NULL)
+		printf("\nUnknown Board\n");
+	else
+		printf("\nBoard: %s\n", board_name);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+int board_mmc_init(bd_t *bis)
+{
+	int ret;
+	/* dwmmc initializattion for available channels */
+	ret = exynos_dwmmc_init(gd->fdt_blob);
+	if (ret)
+		debug("dwmmc init failed\n");
+
+	return ret;
+}
+#endif
+
+static int board_uart_init(void)
+{
+	int err, uart_id, ret = 0;
+
+	for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
+		err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
+		if (err) {
+			debug("UART%d not configured\n",
+			      (uart_id - PERIPH_ID_UART0));
+			ret |= err;
+		}
+	}
+	return ret;
+}
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+	int err;
+	err = board_uart_init();
+	if (err) {
+		debug("UART init failed\n");
+		return err;
+	}
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+	board_i2c_init(gd->fdt_blob);
+#endif
+	return err;
+}
+#endif
+
+#ifdef CONFIG_LCD
+void exynos_cfg_lcd_gpio(void)
+{
+	struct exynos5_gpio_part1 *gpio1 =
+		(struct exynos5_gpio_part1 *)samsung_get_base_gpio_part1();
+
+	/* For Backlight */
+	s5p_gpio_cfg_pin(&gpio1->b2, 0, GPIO_OUTPUT);
+	s5p_gpio_set_value(&gpio1->b2, 0, 1);
+
+	/* LCD power on */
+	s5p_gpio_cfg_pin(&gpio1->x1, 5, GPIO_OUTPUT);
+	s5p_gpio_set_value(&gpio1->x1, 5, 1);
+
+	/* Set Hotplug detect for DP */
+	s5p_gpio_cfg_pin(&gpio1->x0, 7, GPIO_FUNC(0x3));
+}
+
+void exynos_set_dp_phy(unsigned int onoff)
+{
+	set_dp_phy_ctrl(onoff);
+}
+#endif
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+	stdio_print_current_devices();
+
+	if (local.cros_ec_err) {
+		/* Force console on */
+		gd->flags &= ~GD_FLG_SILENT;
+
+		printf("cros-ec communications failure %d\n",
+		       local.cros_ec_err);
+		puts("\nPlease reset with Power+Refresh\n\n");
+		panic("Cannot init cros-ec device");
+		return -1;
+	}
+	return 0;
+}
+#endif
diff --git a/board/samsung/smdk5250/lowlevel_init.S b/board/samsung/smdk5250/lowlevel_init.S
index bc6cb6f..edc565e 100644
--- a/board/samsung/smdk5250/lowlevel_init.S
+++ b/board/samsung/smdk5250/lowlevel_init.S
@@ -75,12 +75,14 @@
 	bl	mem_ctrl_init
 
 1:
+	bl	arch_cpu_init
 	bl	tzpc_init
 	ldmia	r13!, {ip,pc}
 
 wakeup_reset:
 	bl	system_clock_init
 	bl	mem_ctrl_init
+	bl	arch_cpu_init
 	bl	tzpc_init
 
 exit_wakeup:
diff --git a/board/samsung/smdk5250/setup.h b/board/samsung/smdk5250/setup.h
index 34d8bc31..eb91d13 100644
--- a/board/samsung/smdk5250/setup.h
+++ b/board/samsung/smdk5250/setup.h
@@ -28,18 +28,6 @@
 #include <config.h>
 #include <asm/arch/dmc.h>
 
-/* TZPC : Register Offsets */
-#define TZPC0_BASE		0x10100000
-#define TZPC1_BASE		0x10110000
-#define TZPC2_BASE		0x10120000
-#define TZPC3_BASE		0x10130000
-#define TZPC4_BASE		0x10140000
-#define TZPC5_BASE		0x10150000
-#define TZPC6_BASE		0x10160000
-#define TZPC7_BASE		0x10170000
-#define TZPC8_BASE		0x10180000
-#define TZPC9_BASE		0x10190000
-
 /* APLL_CON1	*/
 #define APLL_CON1_VAL	(0x00203800)
 
@@ -458,18 +446,6 @@
 /* CLK_GATE_IP_DISP1 */
 #define CLK_GATE_DP1_ALLOW	(1 << 4)
 
-/*
- * TZPC Register Value :
- * R0SIZE: 0x0 : Size of secured ram
- */
-#define R0SIZE			0x0
-
-/*
- * TZPC Decode Protection Register Value :
- * DECPROTXSET: 0xFF : Set Decode region to non-secure
- */
-#define DECPROTXSET		0xFF
-
 #define DDR3PHY_CTRL_PHY_RESET	(1 << 0)
 #define DDR3PHY_CTRL_PHY_RESET_OFF	(0 << 0)
 
@@ -590,5 +566,4 @@
 void sdelay(unsigned long);
 void mem_ctrl_init(void);
 void system_clock_init(void);
-void tzpc_init(void);
 #endif
diff --git a/board/samsung/smdk5250/smdk5250.c b/board/samsung/smdk5250/smdk5250.c
index 8b09e1d..276fd41 100644
--- a/board/samsung/smdk5250/smdk5250.c
+++ b/board/samsung/smdk5250/smdk5250.c
@@ -29,6 +29,7 @@
 #include <netdev.h>
 #include <spi.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/dwmmc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/pinmux.h>
@@ -37,39 +38,9 @@
 #include <asm/arch/dp_info.h>
 #include <power/pmic.h>
 #include <power/max77686_pmic.h>
-#include <tmu.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined CONFIG_EXYNOS_TMU
-/*
- * Boot Time Thermal Analysis for SoC temperature threshold breach
- */
-static void boot_temp_check(void)
-{
-	int temp;
-
-	switch (tmu_monitor(&temp)) {
-	/* Status TRIPPED ans WARNING means corresponding threshold breach */
-	case TMU_STATUS_TRIPPED:
-		puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
-		set_ps_hold_ctrl();
-		hang();
-		break;
-	case TMU_STATUS_WARNING:
-		puts("EXYNOS_TMU: WARNING! Temperature very high\n");
-		break;
-	/*
-	 * TMU_STATUS_INIT means something is wrong with temperature sensing
-	 * and TMU status was changed back from NORMAL to INIT.
-	 */
-	case TMU_STATUS_INIT:
-	default:
-		debug("EXYNOS_TMU: Unknown TMU state\n");
-	}
-}
-#endif
-
 #ifdef CONFIG_USB_EHCI_EXYNOS
 int board_usb_vbus_init(void)
 {
@@ -102,14 +73,6 @@
 {
 	gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
 
-#if defined CONFIG_EXYNOS_TMU
-	if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
-		debug("%s: Failed to init TMU\n", __func__);
-		return -1;
-	}
-	boot_temp_check();
-#endif
-
 #ifdef CONFIG_EXYNOS_SPI
 	spi_init();
 #endif
@@ -124,14 +87,13 @@
 
 int dram_init(void)
 {
-	gd->ram_size	= get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_3, PHYS_SDRAM_3_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_4, PHYS_SDRAM_4_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_5, PHYS_SDRAM_7_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_6, PHYS_SDRAM_7_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_7, PHYS_SDRAM_7_SIZE)
-			+ get_ram_size((long *)PHYS_SDRAM_8, PHYS_SDRAM_8_SIZE);
+	int i;
+	u32 addr;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+		gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+	}
 	return 0;
 }
 
@@ -254,57 +216,15 @@
 
 void dram_init_banksize(void)
 {
-	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-	gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1,
-							PHYS_SDRAM_1_SIZE);
-	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
-	gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2,
-							PHYS_SDRAM_2_SIZE);
-	gd->bd->bi_dram[2].start = PHYS_SDRAM_3;
-	gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3,
-							PHYS_SDRAM_3_SIZE);
-	gd->bd->bi_dram[3].start = PHYS_SDRAM_4;
-	gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4,
-							PHYS_SDRAM_4_SIZE);
-	gd->bd->bi_dram[4].start = PHYS_SDRAM_5;
-	gd->bd->bi_dram[4].size = get_ram_size((long *)PHYS_SDRAM_5,
-							PHYS_SDRAM_5_SIZE);
-	gd->bd->bi_dram[5].start = PHYS_SDRAM_6;
-	gd->bd->bi_dram[5].size = get_ram_size((long *)PHYS_SDRAM_6,
-							PHYS_SDRAM_6_SIZE);
-	gd->bd->bi_dram[6].start = PHYS_SDRAM_7;
-	gd->bd->bi_dram[6].size = get_ram_size((long *)PHYS_SDRAM_7,
-							PHYS_SDRAM_7_SIZE);
-	gd->bd->bi_dram[7].start = PHYS_SDRAM_8;
-	gd->bd->bi_dram[7].size = get_ram_size((long *)PHYS_SDRAM_8,
-							PHYS_SDRAM_8_SIZE);
-}
-
-#ifdef CONFIG_OF_CONTROL
-static int decode_sromc(const void *blob, struct fdt_sromc *config)
-{
-	int err;
-	int node;
-
-	node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
-	if (node < 0) {
-		debug("Could not find SROMC node\n");
-		return node;
+	int i;
+	u32 addr, size;
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+		size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+		gd->bd->bi_dram[i].start = addr;
+		gd->bd->bi_dram[i].size = size;
 	}
-
-	config->bank = fdtdec_get_int(blob, node, "bank", 0);
-	config->width = fdtdec_get_int(blob, node, "width", 2);
-
-	err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
-			FDT_SROM_TIMING_COUNT);
-	if (err < 0) {
-		debug("Could not decode SROMC configuration\n");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	return 0;
 }
-#endif
 
 int board_eth_init(bd_t *bis)
 {
@@ -313,27 +233,6 @@
 	struct fdt_sromc config;
 	fdt_addr_t base_addr;
 
-#ifdef CONFIG_OF_CONTROL
-	int node;
-
-	node = decode_sromc(gd->fdt_blob, &config);
-	if (node < 0) {
-		debug("%s: Could not find sromc configuration\n", __func__);
-		return 0;
-	}
-	node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
-	if (node < 0) {
-		debug("%s: Could not find lan9215 configuration\n", __func__);
-		return 0;
-	}
-
-	/* We now have a node, so any problems from now on are errors */
-	base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
-	if (base_addr == FDT_ADDR_T_NONE) {
-		debug("%s: Could not find lan9215 address\n", __func__);
-		return -1;
-	}
-#else
 	/* Non-FDT configuration - bank number and timing parameters*/
 	config.bank = CONFIG_ENV_SROM_BANK;
 	config.width = 2;
@@ -346,7 +245,6 @@
 	config.timing[FDT_SROM_TACP] = 0x09;
 	config.timing[FDT_SROM_PMC] = 0x01;
 	base_addr = CONFIG_SMC911X_BASE;
-#endif
 
 	/* Ethernet needs data bus width of 16 bits */
 	if (config.width != 2) {
@@ -376,17 +274,7 @@
 #ifdef CONFIG_DISPLAY_BOARDINFO
 int checkboard(void)
 {
-#ifdef CONFIG_OF_CONTROL
-	const char *board_name;
-
-	board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
-	if (board_name == NULL)
-		printf("\nUnknown Board\n");
-	else
-		printf("\nBoard: %s\n", board_name);
-#else
 	printf("\nBoard: SMDK5250\n");
-#endif
 	return 0;
 }
 #endif
@@ -394,48 +282,54 @@
 #ifdef CONFIG_GENERIC_MMC
 int board_mmc_init(bd_t *bis)
 {
-	int err;
+	int err, ret = 0, index, bus_width;
+	u32 base;
 
 	err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
-	if (err) {
+	if (err)
 		debug("SDMMC0 not configured\n");
-		return err;
-	}
+	ret |= err;
 
-	err = s5p_mmc_init(0, 8);
-	return err;
+	/*EMMC: dwmmc Channel-0 with 8 bit bus width */
+	index = 0;
+	base =  samsung_get_base_mmc() + (0x10000 * index);
+	bus_width = 8;
+	err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
+	if (err)
+		debug("dwmmc Channel-0 init failed\n");
+	ret |= err;
+
+	err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE);
+	if (err)
+		debug("SDMMC2 not configured\n");
+	ret |= err;
+
+	/*SD: dwmmc Channel-2 with 4 bit bus width */
+	index = 2;
+	base = samsung_get_base_mmc() + (0x10000 * index);
+	bus_width = 4;
+	err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
+	if (err)
+		debug("dwmmc Channel-2 init failed\n");
+	ret |= err;
+
+	return ret;
 }
 #endif
 
 static int board_uart_init(void)
 {
-	int err;
+	int err, uart_id, ret = 0;
 
-	err = exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE);
-	if (err) {
-		debug("UART0 not configured\n");
-		return err;
+	for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
+		err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
+		if (err) {
+			debug("UART%d not configured\n",
+			      (uart_id - PERIPH_ID_UART0));
+			ret |= err;
+		}
 	}
-
-	err = exynos_pinmux_config(PERIPH_ID_UART1, PINMUX_FLAG_NONE);
-	if (err) {
-		debug("UART1 not configured\n");
-		return err;
-	}
-
-	err = exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE);
-	if (err) {
-		debug("UART2 not configured\n");
-		return err;
-	}
-
-	err = exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
-	if (err) {
-		debug("UART3 not configured\n");
-		return err;
-	}
-
-	return 0;
+	return ret;
 }
 
 #ifdef CONFIG_BOARD_EARLY_INIT_F
@@ -448,7 +342,7 @@
 		return err;
 	}
 #ifdef CONFIG_SYS_I2C_INIT_BOARD
-	board_i2c_init(gd->fdt_blob);
+	board_i2c_init(NULL);
 #endif
 	return err;
 }
@@ -477,7 +371,6 @@
 	set_dp_phy_ctrl(onoff);
 }
 
-#ifndef CONFIG_OF_CONTROL
 vidinfo_t panel_info = {
 	.vl_freq	= 60,
 	.vl_col		= 2560,
@@ -543,13 +436,9 @@
 	.edp_dev_info	= &edp_info,
 };
 
-#endif
 void init_panel_info(vidinfo_t *vid)
 {
-#ifndef CONFIG_OF_CONTROL
-	vid->rgb_mode   = MODE_RGB_P,
-
+	vid->rgb_mode   = MODE_RGB_P;
 	exynos_set_dp_platform_data(&dp_platform_data);
-#endif
 }
 #endif
diff --git a/board/samsung/smdk5250/spl_boot.c b/board/samsung/smdk5250/spl_boot.c
index c0bcf46..98f2286 100644
--- a/board/samsung/smdk5250/spl_boot.c
+++ b/board/samsung/smdk5250/spl_boot.c
@@ -23,16 +23,44 @@
 #include<common.h>
 #include<config.h>
 
+#include <asm/arch-exynos/dmc.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/clk.h>
+
+#include "clock_init.h"
+
+/* Index into irom ptr table */
+enum index {
+	MMC_INDEX,
+	EMMC44_INDEX,
+	EMMC44_END_INDEX,
+	SPI_INDEX,
+	USB_INDEX,
+};
+
+/* IROM Function Pointers Table */
+u32 irom_ptr_table[] = {
+	[MMC_INDEX] = 0x02020030,	/* iROM Function Pointer-SDMMC boot */
+	[EMMC44_INDEX] = 0x02020044,	/* iROM Function Pointer-EMMC4.4 boot*/
+	[EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer
+						-EMMC4.4 end boot operation */
+	[SPI_INDEX] = 0x02020058,	/* iROM Function Pointer-SPI boot */
+	[USB_INDEX] = 0x02020070,	/* iROM Function Pointer-USB boot*/
+	};
+
 enum boot_mode {
 	BOOT_MODE_MMC = 4,
 	BOOT_MODE_SERIAL = 20,
+	BOOT_MODE_EMMC = 8,     /* EMMC4.4 */
 	/* Boot based on Operating Mode pin settings */
 	BOOT_MODE_OM = 32,
 	BOOT_MODE_USB,	/* Boot using USB download */
 };
 
-	typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst);
-	typedef u32 (*usb_copy_func_t)(void);
+void *get_irom_func(int index)
+{
+	return (void *)*(u32 *)irom_ptr_table[index];
+}
 
 /*
  * Set/clear program flow prediction and return the previous state.
@@ -55,13 +83,15 @@
 */
 void copy_uboot_to_ram(void)
 {
-	spi_copy_func_t spi_copy;
-	usb_copy_func_t usb_copy;
-
 	int is_cr_z_set;
 	unsigned int sec_boot_check;
 	enum boot_mode bootmode = BOOT_MODE_OM;
-	u32 (*copy_bl2)(u32, u32, u32);
+
+	u32 (*spi_copy)(u32 offset, u32 nblock, u32 dst);
+	u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst);
+	u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst);
+	void (*end_bootop_from_emmc)(void);
+	u32 (*usb_copy)(void);
 
 	/* Read iRAM location to check for secondary USB boot mode */
 	sec_boot_check = readl(EXYNOS_IRAM_SECONDARY_BASE);
@@ -73,14 +103,24 @@
 
 	switch (bootmode) {
 	case BOOT_MODE_SERIAL:
-		spi_copy = *(spi_copy_func_t *)EXYNOS_COPY_SPI_FNPTR_ADDR;
+		spi_copy = get_irom_func(SPI_INDEX);
 		spi_copy(SPI_FLASH_UBOOT_POS, CONFIG_BL2_SIZE,
-						CONFIG_SYS_TEXT_BASE);
+			 CONFIG_SYS_TEXT_BASE);
 		break;
 	case BOOT_MODE_MMC:
-		copy_bl2 = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR;
+		copy_bl2 = get_irom_func(MMC_INDEX);
 		copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT,
-						CONFIG_SYS_TEXT_BASE);
+			 CONFIG_SYS_TEXT_BASE);
+		break;
+	case BOOT_MODE_EMMC:
+		/* Set the FSYS1 clock divisor value for EMMC boot */
+		emmc_boot_clk_div_set();
+
+		copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX);
+		end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX);
+
+		copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE);
+		end_bootop_from_emmc();
 		break;
 	case BOOT_MODE_USB:
 		/*
@@ -88,8 +128,7 @@
 		 * before copy from USB device to RAM
 		 */
 		is_cr_z_set = config_branch_prediction(0);
-		usb_copy = *(usb_copy_func_t *)
-				EXYNOS_COPY_USB_FNPTR_ADDR;
+		usb_copy = get_irom_func(USB_INDEX);
 		usb_copy();
 		config_branch_prediction(is_cr_z_set);
 		break;
@@ -117,5 +156,4 @@
 	while (1)
 		;
 }
-
 void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
diff --git a/board/samsung/smdkv310/lowlevel_init.S b/board/samsung/smdkv310/lowlevel_init.S
index 7a1ea98..31e0e2e 100644
--- a/board/samsung/smdkv310/lowlevel_init.S
+++ b/board/samsung/smdkv310/lowlevel_init.S
@@ -85,12 +85,14 @@
 1:
 	/* for UART */
 	bl uart_asm_init
+	bl arch_cpu_init
 	bl tzpc_init
 	pop	{pc}
 
 wakeup_reset:
 	bl system_clock_init
 	bl mem_ctrl_asm_init
+	bl arch_cpu_init
 	bl tzpc_init
 
 exit_wakeup:
@@ -410,61 +412,3 @@
 	nop
 	nop
 	nop
-
-/* Setting TZPC[TrustZone Protection Controller] */
-tzpc_init:
-	ldr	r0, =0x10110000
-	mov	r1, #0x0
-	str	r1, [r0]
-	mov	r1, #0xff
-	str	r1, [r0, #0x0804]
-	str	r1, [r0, #0x0810]
-	str	r1, [r0, #0x081C]
-	str	r1, [r0, #0x0828]
-
-	ldr	r0, =0x10120000
-	mov	r1, #0x0
-	str	r1, [r0]
-	mov	r1, #0xff
-	str	r1, [r0, #0x0804]
-	str	r1, [r0, #0x0810]
-	str	r1, [r0, #0x081C]
-	str	r1, [r0, #0x0828]
-
-	ldr	r0, =0x10130000
-	mov	r1, #0x0
-	str	r1, [r0]
-	mov	r1, #0xff
-	str	r1, [r0, #0x0804]
-	str	r1, [r0, #0x0810]
-	str	r1, [r0, #0x081C]
-	str	r1, [r0, #0x0828]
-
-	ldr	r0, =0x10140000
-	mov	r1, #0x0
-	str	r1, [r0]
-	mov	r1, #0xff
-	str	r1, [r0, #0x0804]
-	str	r1, [r0, #0x0810]
-	str	r1, [r0, #0x081C]
-	str	r1, [r0, #0x0828]
-
-	ldr	r0, =0x10150000
-	mov	r1, #0x0
-	str	r1, [r0]
-	mov	r1, #0xff
-	str	r1, [r0, #0x0804]
-	str	r1, [r0, #0x0810]
-	str	r1, [r0, #0x081C]
-	str	r1, [r0, #0x0828]
-
-	ldr	r0, =0x10160000
-	mov	r1, #0x0
-	str	r1, [r0]
-	mov	r1, #0xff
-	str	r1, [r0, #0x0804]
-	str	r1, [r0, #0x0810]
-	str	r1, [r0, #0x081C]
-	str	r1, [r0, #0x0828]
-
-	mov	pc, lr
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index 638cc4d..fdbe26c 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -38,9 +38,6 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-#ifdef CONFIG_SPL_BUILD
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
-#endif
 
 /* MII mode defines */
 #define MII_MODE_ENABLE		0x0
@@ -126,28 +123,7 @@
 	return 0;
 }
 
-/* UART Defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET		(0x1 << 1)
-#define UART_CLK_RUNNING_MASK	0x1
-#define UART_SMART_IDLE_EN	(0x1 << 0x3)
-
-static void rtc32k_enable(void)
-{
-	struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-	/*
-	 * Unlock the RTC's registers.  For more details please see the
-	 * RTC_SS section of the TRM.  In order to unlock we need to
-	 * write these specific values (keys) in this order.
-	 */
-	writel(0x83e70b13, &rtc->kick0r);
-	writel(0x95a4f1e0, &rtc->kick1r);
-
-	/* Enable the RTC 32K OSC by setting bits 3 and 6. */
-	writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static const struct ddr_data ddr2_data = {
 	.datardsratio0 = ((MT47H128M16RT25E_RD_DQS<<30) |
 			  (MT47H128M16RT25E_RD_DQS<<20) |
@@ -339,9 +315,6 @@
 	/* Enable RTC32K clock */
 	rtc32k_enable();
 
-	/* UART softreset */
-	u32 regVal;
-
 #ifdef CONFIG_SERIAL1
 	enable_uart0_pin_mux();
 #endif /* CONFIG_SERIAL1 */
@@ -361,17 +334,7 @@
 	enable_uart5_pin_mux();
 #endif /* CONFIG_SERIAL6 */
 
-	regVal = readl(&uart_base->uartsyscfg);
-	regVal |= UART_RESET;
-	writel(regVal, &uart_base->uartsyscfg);
-	while ((readl(&uart_base->uartsyssts) &
-		UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
-		;
-
-	/* Disable smart idle */
-	regVal = readl(&uart_base->uartsyscfg);
-	regVal |= UART_SMART_IDLE_EN;
-	writel(regVal, &uart_base->uartsyscfg);
+	uart_soft_reset();
 
 	gd = &gdata;
 
diff --git a/board/ti/panda/panda.c b/board/ti/panda/panda.c
index 90ae29e..1da5b35 100644
--- a/board/ti/panda/panda.c
+++ b/board/ti/panda/panda.c
@@ -37,6 +37,11 @@
 #endif
 
 #define PANDA_ULPI_PHY_TYPE_GPIO       182
+#define PANDA_BOARD_ID_1_GPIO          101
+#define PANDA_ES_BOARD_ID_1_GPIO        48
+#define PANDA_BOARD_ID_2_GPIO          171
+#define PANDA_ES_BOARD_ID_3_GPIO         3
+#define PANDA_ES_BOARD_ID_4_GPIO         2
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -66,6 +71,73 @@
 	return 0;
 }
 
+/*
+* Routine: get_board_revision
+* Description: Detect if we are running on a panda revision A1-A6,
+*              or an ES panda board. This can be done by reading
+*              the level of GPIOs and checking the processor revisions.
+*              This should result in:
+*			Panda 4430:
+*              GPIO171, GPIO101, GPIO182: 0 1 1 => A1-A5
+*              GPIO171, GPIO101, GPIO182: 1 0 1 => A6
+*			Panda ES:
+*              GPIO2, GPIO3, GPIO171, GPIO48, GPIO182: 0 0 0 1 1 => B1/B2
+*              GPIO2, GPIO3, GPIO171, GPIO48, GPIO182: 0 0 1 1 1 => B3
+*/
+int get_board_revision(void)
+{
+	int board_id0, board_id1, board_id2;
+	int board_id3, board_id4;
+	int board_id;
+
+	int processor_rev = omap_revision();
+
+	/* Setup the mux for the common board ID pins (gpio 171 and 182) */
+	writew((IEN | M3), (*ctrl)->control_padconf_core_base + UNIPRO_TX0);
+	writew((IEN | M3), (*ctrl)->control_padconf_core_base + FREF_CLK2_OUT);
+
+	board_id0 = gpio_get_value(PANDA_ULPI_PHY_TYPE_GPIO);
+	board_id2 = gpio_get_value(PANDA_BOARD_ID_2_GPIO);
+
+	if ((processor_rev >= OMAP4460_ES1_0 &&
+	     processor_rev <= OMAP4460_ES1_1)) {
+		/*
+		 * Setup the mux for the ES specific board ID pins (gpio 101,
+		 * 2 and 3.
+		 */
+		writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+				GPMC_A24);
+		writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+				UNIPRO_RY0);
+		writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+				UNIPRO_RX1);
+
+		board_id1 = gpio_get_value(PANDA_ES_BOARD_ID_1_GPIO);
+		board_id3 = gpio_get_value(PANDA_ES_BOARD_ID_3_GPIO);
+		board_id4 = gpio_get_value(PANDA_ES_BOARD_ID_4_GPIO);
+
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+		setenv("board_name", strcat(CONFIG_SYS_BOARD, "-es"));
+#endif
+		board_id = ((board_id4 << 4) | (board_id3 << 3) |
+			(board_id2 << 2) | (board_id1 << 1) | (board_id0));
+	} else {
+		/* Setup the mux for the Ax specific board ID pins (gpio 101) */
+		writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+				FREF_CLK2_OUT);
+
+		board_id1 = gpio_get_value(PANDA_BOARD_ID_1_GPIO);
+		board_id = ((board_id2 << 2) | (board_id1 << 1) | (board_id0));
+
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+		if ((board_id >= 0x3) && (processor_rev == OMAP4430_ES2_3))
+			setenv("board_name", strcat(CONFIG_SYS_BOARD, "-a4"));
+#endif
+	}
+
+	return board_id;
+}
+
 /**
  * @brief misc_init_r - Configure Panda board specific configurations
  * such as power configurations, ethernet initialization as phase2 of
@@ -82,11 +154,7 @@
 	if (omap_revision() == OMAP4430_ES1_0)
 		return 0;
 
-#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
-	if (omap_revision() >= OMAP4460_ES1_0 ||
-		omap_revision() <= OMAP4460_ES1_1)
-		setenv("board_name", strcat(CONFIG_SYS_BOARD, "-es"));
-#endif
+	get_board_revision();
 
 	gpio_direction_input(PANDA_ULPI_PHY_TYPE_GPIO);
 	phy_type = gpio_get_value(PANDA_ULPI_PHY_TYPE_GPIO);
@@ -106,7 +174,7 @@
 		auxclk |= AUXCLK_ENABLE_MASK;
 
 		writel(auxclk, &scrm->auxclk3);
-       } else {
+	} else {
 		/* ULPI PHY supplied by auxclk1 derived from PER dpll */
 		debug("ULPI PHY supplied by auxclk1\n");
 
@@ -151,9 +219,9 @@
 
 	if (omap_revision() >= OMAP4460_ES1_0)
 		do_set_mux((*ctrl)->control_padconf_wkup_base,
-				 wkup_padconf_array_essential_4460,
-				 sizeof(wkup_padconf_array_essential_4460) /
-				 sizeof(struct pad_conf_entry));
+			   wkup_padconf_array_essential_4460,
+			   sizeof(wkup_padconf_array_essential_4460) /
+			   sizeof(struct pad_conf_entry));
 }
 
 void set_muxconf_regs_non_essential(void)
@@ -165,14 +233,14 @@
 
 	if (omap_revision() < OMAP4460_ES1_0)
 		do_set_mux((*ctrl)->control_padconf_core_base,
-				core_padconf_array_non_essential_4430,
-				sizeof(core_padconf_array_non_essential_4430) /
-				sizeof(struct pad_conf_entry));
+			   core_padconf_array_non_essential_4430,
+			   sizeof(core_padconf_array_non_essential_4430) /
+			   sizeof(struct pad_conf_entry));
 	else
 		do_set_mux((*ctrl)->control_padconf_core_base,
-				core_padconf_array_non_essential_4460,
-				sizeof(core_padconf_array_non_essential_4460) /
-				sizeof(struct pad_conf_entry));
+			   core_padconf_array_non_essential_4460,
+			   sizeof(core_padconf_array_non_essential_4460) /
+			   sizeof(struct pad_conf_entry));
 
 	do_set_mux((*ctrl)->control_padconf_wkup_base,
 		   wkup_padconf_array_non_essential,
@@ -181,9 +249,9 @@
 
 	if (omap_revision() < OMAP4460_ES1_0)
 		do_set_mux((*ctrl)->control_padconf_wkup_base,
-				wkup_padconf_array_non_essential_4430,
-				sizeof(wkup_padconf_array_non_essential_4430) /
-				sizeof(struct pad_conf_entry));
+			   wkup_padconf_array_non_essential_4430,
+			   sizeof(wkup_padconf_array_non_essential_4430) /
+			   sizeof(struct pad_conf_entry));
 }
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_GENERIC_MMC)
diff --git a/board/ti/ti814x/evm.c b/board/ti/ti814x/evm.c
index 4759b16..6ad3dd8 100644
--- a/board/ti/ti814x/evm.c
+++ b/board/ti/ti814x/evm.c
@@ -37,49 +37,16 @@
 
 #ifdef CONFIG_SPL_BUILD
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
 #endif
 
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
 
 /* UART Defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET		(0x1 << 1)
-#define UART_CLK_RUNNING_MASK	0x1
-#define UART_SMART_IDLE_EN	(0x1 << 0x3)
-
-static void rtc32k_enable(void)
-{
-	struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-	/*
-	 * Unlock the RTC's registers.  For more details please see the
-	 * RTC_SS section of the TRM.  In order to unlock we need to
-	 * write these specific values (keys) in this order.
-	 */
-	writel(0x83e70b13, &rtc->kick0r);
-	writel(0x95a4f1e0, &rtc->kick1r);
-
-	/* Enable the RTC 32K OSC by setting bits 3 and 6. */
-	writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static void uart_enable(void)
 {
-	u32 regVal;
-
 	/* UART softreset */
-	regVal = readl(&uart_base->uartsyscfg);
-	regVal |= UART_RESET;
-	writel(regVal, &uart_base->uartsyscfg);
-	while ((readl(&uart_base->uartsyssts) &
-		UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
-		;
-
-	/* Disable smart idle */
-	regVal = readl(&uart_base->uartsyscfg);
-	regVal |= UART_SMART_IDLE_EN;
-	writel(regVal, &uart_base->uartsyscfg);
+	uart_soft_reset();
 }
 
 static void wdt_disable(void)
diff --git a/board/vpac270/u-boot-spl.lds b/board/vpac270/u-boot-spl.lds
index 61d1154..1a3ef92 100644
--- a/board/vpac270/u-boot-spl.lds
+++ b/board/vpac270/u-boot-spl.lds
@@ -67,11 +67,6 @@
 		__rel_dyn_end = .;
 	}
 
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	}
-
 	. = ALIGN(0x800);
 
 	_end = .;
@@ -84,6 +79,7 @@
 	}
 
 	/DISCARD/ : { *(.bss*) }
+	/DISCARD/ : { *(.dynsym) }
 	/DISCARD/ : { *(.dynstr*) }
 	/DISCARD/ : { *(.dynsym*) }
 	/DISCARD/ : { *(.dynamic*) }
diff --git a/boards.cfg b/boards.cfg
index 1e598cb..c0c4282 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -831,6 +831,7 @@
 P1022DS_SDCARD               powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:SDCARD
 P1022DS_36BIT_SDCARD         powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:36BIT,SDCARD
 P1022DS_36BIT                powerpc     mpc85xx     p1022ds             freescale      -           P1022DS:36BIT
+P1023RDB                     powerpc     mpc85xx     p1023rdb            freescale      -           P1023RDB
 P1023RDS                     powerpc     mpc85xx     p1023rds            freescale      -           P1023RDS
 P1023RDS_NAND                powerpc     mpc85xx     p1023rds            freescale      -           P1023RDS:NAND
 P1024RDB                     powerpc     mpc85xx     p1_p2_rdb_pc        freescale      -           p1_p2_rdb_pc:P1024RDB
@@ -900,8 +901,13 @@
 P5040DS_SDCARD		     powerpc     mpc85xx     corenet_ds          freescale      -           P5040DS:RAMBOOT_PBL,SDCARD,SYS_TEXT_BASE=0xFFF80000
 P5040DS_SPIFLASH	     powerpc     mpc85xx     corenet_ds          freescale      -           P5040DS:RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
 BSC9131RDB_SPIFLASH          powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,SPIFLASH
+BSC9131RDB_SPIFLASH_SYSCLK100 powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,SPIFLASH,SYS_CLK_100
+BSC9131RDB_NAND              powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,NAND
+BSC9131RDB_NAND_SYSCLK100    powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,NAND,SYS_CLK_100
 BSC9132QDS_NOR_DDRCLK100     powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SYS_CLK_100_DDR_100
 BSC9132QDS_NOR_DDRCLK133     powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SYS_CLK_100_DDR_133
+BSC9132QDS_NAND_DDRCLK100    powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,NAND,SYS_CLK_100_DDR_100
+BSC9132QDS_NAND_DDRCLK133    powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,NAND,SYS_CLK_100_DDR_133
 BSC9132QDS_SDCARD_DDRCLK100  powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SDCARD,SYS_CLK_100_DDR_100
 BSC9132QDS_SDCARD_DDRCLK133  powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SDCARD,SYS_CLK_100_DDR_133
 BSC9132QDS_SPIFLASH_DDRCLK100 powerpc    mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SPIFLASH,SYS_CLK_100_DDR_100
@@ -912,12 +918,14 @@
 T4240QDS                     powerpc     mpc85xx     t4qds               freescale      -           T4240QDS:PPC_T4240
 T4240QDS_SDCARD              powerpc     mpc85xx     t4qds               freescale	-           T4240QDS:PPC_T4240,RAMBOOT_PBL,SDCARD,SYS_TEXT_BASE=0xFFF80000
 T4240QDS_SPIFLASH            powerpc     mpc85xx     t4qds               freescale	-           T4240QDS:PPC_T4240,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
+T4240QDS_SRIO_PCIE_BOOT	     powerpc     mpc85xx     t4qds               freescale      -           T4240QDS:PPC_T4240,SRIO_PCIE_BOOT_SLAVE,SYS_TEXT_BASE=0xFFF80000
 T4160QDS                     powerpc     mpc85xx     t4qds               freescale      -           T4240QDS:PPC_T4160
 T4160QDS_SDCARD              powerpc     mpc85xx     t4qds               freescale	-           T4240QDS:PPC_T4160,RAMBOOT_PBL,SDCARD,SYS_TEXT_BASE=0xFFF80000
 T4160QDS_SPIFLASH            powerpc     mpc85xx     t4qds               freescale	-           T4240QDS:PPC_T4160,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
 B4860QDS                     powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4860
 B4860QDS_NAND		     powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4860,RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF80000
 B4860QDS_SPIFLASH            powerpc     mpc85xx     b4860qds            freescale	-           B4860QDS:PPC_B4860,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
+B4860QDS_SRIO_PCIE_BOOT	     powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4860,SRIO_PCIE_BOOT_SLAVE,SYS_TEXT_BASE=0xFFF80000
 B4420QDS                     powerpc     mpc85xx     b4860qds            freescale	-	    B4860QDS:PPC_B4420
 B4420QDS_NAND		     powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4420,RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF80000
 B4420QDS_SPIFLASH            powerpc     mpc85xx     b4860qds            freescale	-           B4860QDS:PPC_B4420,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
diff --git a/common/Makefile b/common/Makefile
index 3ba4316..48791b7 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -44,13 +44,11 @@
 COBJS-y += cmd_boot.o
 COBJS-$(CONFIG_CMD_BOOTM) += cmd_bootm.o
 COBJS-y += cmd_help.o
-COBJS-y += cmd_nvedit.o
 COBJS-y += cmd_version.o
 
 # environment
 COBJS-y += env_attr.o
 COBJS-y += env_callback.o
-COBJS-y += env_common.o
 COBJS-y += env_flags.o
 COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
 COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
@@ -171,6 +169,7 @@
 COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o
 COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o
 COBJS-$(CONFIG_CMD_TIME) += cmd_time.o
+COBJS-$(CONFIG_CMD_TRACE) += cmd_trace.o
 COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o
 COBJS-$(CONFIG_CMD_TPM) += cmd_tpm.o
 COBJS-$(CONFIG_CMD_TSI148) += cmd_tsi148.o
@@ -191,14 +190,6 @@
 COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o
 
 # others
-ifdef CONFIG_DDR_SPD
-SPD := y
-endif
-ifdef CONFIG_SPD_EEPROM
-SPD := y
-endif
-COBJS-$(SPD) += ddr_spd.o
-COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
 COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o
 COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
 COBJS-y += flash.o
@@ -216,24 +207,43 @@
 endif
 
 ifdef CONFIG_SPL_BUILD
-COBJS-y += cmd_nvedit.o
-COBJS-y += env_common.o
 COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
 COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += cmd_nvedit.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_attr.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_callback.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_common.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_flags.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_nowhere.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
+# environment
+COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
+COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
+COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
+ifneq ($(CONFIG_SPL_NET_SUPPORT),y)
+COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
+COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
+COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
+COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
+COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
+else
+COBJS-y += env_nowhere.o
 endif
+endif
+# core command
+COBJS-y += cmd_nvedit.o
+#environment
+COBJS-y += env_common.o
+#others
+ifdef CONFIG_DDR_SPD
+SPD := y
+endif
+ifdef CONFIG_SPD_EEPROM
+SPD := y
+endif
+COBJS-$(SPD) += ddr_spd.o
+COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
 COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-$(CONFIG_OF_LIBFDT) += image-fdt.o
 COBJS-$(CONFIG_FIT) += image-fit.o
+COBJS-$(CONFIG_FIT_SIGNATURE) += image-sig.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
 
diff --git a/common/board_f.c b/common/board_f.c
index 8efdb63..ab4242a 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -53,6 +53,7 @@
 #include <os.h>
 #include <post.h>
 #include <spi.h>
+#include <trace.h>
 #include <watchdog.h>
 #include <asm/errno.h>
 #include <asm/io.h>
@@ -500,6 +501,18 @@
 }
 #endif /* CONFIG_LCD */
 
+static int reserve_trace(void)
+{
+#ifdef CONFIG_TRACE
+	gd->relocaddr -= CONFIG_TRACE_BUFFER_SIZE;
+	gd->trace_buff = map_sysmem(gd->relocaddr, CONFIG_TRACE_BUFFER_SIZE);
+	debug("Reserving %dk for trace data at: %08lx\n",
+	      CONFIG_TRACE_BUFFER_SIZE >> 10, gd->relocaddr);
+#endif
+
+	return 0;
+}
+
 #if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) \
 		&& !defined(CONFIG_ARM) && !defined(CONFIG_X86)
 static int reserve_video(void)
@@ -818,8 +831,9 @@
 #ifdef CONFIG_SANDBOX
 	setup_ram_buf,
 #endif
-	setup_fdt,
 	setup_mon_len,
+	setup_fdt,
+	trace_early_init,
 #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
 	/* TODO: can this go into arch_cpu_init()? */
 	probecpu,
@@ -963,6 +977,7 @@
 #ifdef CONFIG_LCD
 	reserve_lcd,
 #endif
+	reserve_trace,
 	/* TODO: Why the dependency on CONFIG_8xx? */
 #if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) \
 		&& !defined(CONFIG_ARM) && !defined(CONFIG_X86)
diff --git a/common/board_r.c b/common/board_r.c
index f5649c9..f7a036e 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -58,6 +58,7 @@
 #include <serial.h>
 #include <spi.h>
 #include <stdio_dev.h>
+#include <trace.h>
 #include <watchdog.h>
 #ifdef CONFIG_ADDR_MAP
 #include <asm/mmu.h>
@@ -106,6 +107,15 @@
 	return 0;
 }
 
+static int initr_trace(void)
+{
+#ifdef CONFIG_TRACE
+	trace_init(gd->trace_buff, CONFIG_TRACE_BUFFER_SIZE);
+#endif
+
+	return 0;
+}
+
 static int initr_reloc(void)
 {
 	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
@@ -711,6 +721,7 @@
  * TODO: perhaps reset the watchdog in the initcall function after each call?
  */
 init_fnc_t init_sequence_r[] = {
+	initr_trace,
 	initr_reloc,
 	/* TODO: could x86/PPC have this also perhaps? */
 #ifdef CONFIG_ARM
diff --git a/common/bootstage.c b/common/bootstage.c
index c5c6996..94a32a9 100644
--- a/common/bootstage.c
+++ b/common/bootstage.c
@@ -49,6 +49,7 @@
 enum {
 	BOOTSTAGE_VERSION	= 0,
 	BOOTSTAGE_MAGIC		= 0xb00757a3,
+	BOOTSTAGE_DIGITS	= 9,
 };
 
 struct bootstage_hdr {
@@ -165,21 +166,6 @@
 	return duration;
 }
 
-static void print_time(unsigned long us_time)
-{
-	char str[15], *s;
-	int grab = 3;
-
-	/* We don't seem to have %'d in U-Boot */
-	sprintf(str, "%12lu", us_time);
-	for (s = str + 3; *s; s += grab) {
-		if (s != str + 3)
-			putc(s[-1] != ' ' ? ',' : ' ');
-		printf("%.*s", grab, s);
-		grab = 3;
-	}
-}
-
 /**
  * Get a record name as a printable string
  *
@@ -208,10 +194,10 @@
 
 	if (prev == -1U) {
 		printf("%11s", "");
-		print_time(rec->time_us);
+		print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS);
 	} else {
-		print_time(rec->time_us);
-		print_time(rec->time_us - prev);
+		print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS);
+		print_grouped_ull(rec->time_us - prev, BOOTSTAGE_DIGITS);
 	}
 	printf("  %s\n", get_record_name(buf, sizeof(buf), rec));
 
@@ -445,9 +431,9 @@
 	}
 
 	if (hdr->count * sizeof(*rec) > hdr->size) {
-		debug("%s: Bootstage has %d records needing %d bytes, but "
+		debug("%s: Bootstage has %d records needing %lu bytes, but "
 			"only %d bytes is available\n", __func__, hdr->count,
-		      hdr->count * sizeof(*rec), hdr->size);
+		      (ulong)hdr->count * sizeof(*rec), hdr->size);
 		return -1;
 	}
 
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 05130b6..02a5013 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -104,9 +104,18 @@
  *  - verified image architecture (PPC) and type (KERNEL or MULTI),
  *  - loaded (first part of) image to header load address,
  *  - disabled interrupts.
+ *
+ * @flag: Flags indicating what to do (BOOTM_STATE_...)
+ * @argc: Number of arguments. Note that the arguments are shifted down
+ *	 so that 0 is the first argument not processed by U-Boot, and
+ *	 argc is adjusted accordingly. This avoids confusion as to how
+ *	 many arguments are available for the OS.
+ * @images: Pointers to os/initrd/fdt
+ * @return 1 on error. On success the OS boots so this function does
+ * not return.
  */
 typedef int boot_os_fn(int flag, int argc, char * const argv[],
-			bootm_headers_t *images); /* pointers to os/initrd/fdt */
+			bootm_headers_t *images);
 
 #ifdef CONFIG_BOOTM_LINUX
 extern boot_os_fn do_bootm_linux;
@@ -199,15 +208,21 @@
 
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	const void *os_hdr;
-	int ret;
-
 	memset((void *)&images, 0, sizeof(images));
 	images.verify = getenv_yesno("verify");
 
 	boot_start_lmb(&images);
 
 	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
+	images.state = BOOTM_STATE_START;
+
+	return 0;
+}
+
+static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char * const argv[])
+{
+	const void *os_hdr;
 
 	/* get kernel image header, start address and length */
 	os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -270,6 +285,8 @@
 		images.ep = image_get_ep(&images.legacy_hdr_os_copy);
 #if defined(CONFIG_FIT)
 	} else if (images.fit_uname_os) {
+		int ret;
+
 		ret = fit_image_get_entry(images.fit_hdr_os,
 					  images.fit_noffset_os, &images.ep);
 		if (ret) {
@@ -287,6 +304,16 @@
 		images.ep += images.os.load;
 	}
 
+	images.os.start = (ulong)os_hdr;
+
+	return 0;
+}
+
+static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc,
+			    char * const argv[])
+{
+	int ret;
+
 	if (((images.os.type == IH_TYPE_KERNEL) ||
 	     (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
 	     (images.os.type == IH_TYPE_MULTI)) &&
@@ -312,17 +339,16 @@
 #endif
 	}
 
-	images.os.start = (ulong)os_hdr;
-	images.state = BOOTM_STATE_START;
-
 	return 0;
 }
 
 #define BOOTM_ERR_RESET		-1
 #define BOOTM_ERR_OVERLAP	-2
 #define BOOTM_ERR_UNIMPLEMENTED	-3
-static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
+static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
+		int boot_progress)
 {
+	image_info_t os = images->os;
 	uint8_t comp = os.comp;
 	ulong load = os.load;
 	ulong blob_start = os.start;
@@ -440,13 +466,23 @@
 		debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
 			*load_end);
 
-		return BOOTM_ERR_OVERLAP;
+		/* Check what type of image this is. */
+		if (images->legacy_hdr_valid) {
+			if (image_get_type(&images->legacy_hdr_os_copy)
+					== IH_TYPE_MULTI)
+				puts("WARNING: legacy format multi component image overwritten\n");
+			return BOOTM_ERR_OVERLAP;
+		} else {
+			puts("ERROR: new format image overwritten - must RESET the board to recover\n");
+			bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
+			return BOOTM_ERR_RESET;
+		}
 	}
 
 	return 0;
 }
 
-static int bootm_start_standalone(ulong iflag, int argc, char * const argv[])
+static int bootm_start_standalone(int argc, char * const argv[])
 {
 	char  *s;
 	int   (*appl)(int, char * const []);
@@ -457,7 +493,7 @@
 		return 0;
 	}
 	appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
-	(*appl)(argc-1, &argv[1]);
+	(*appl)(argc, argv);
 	return 0;
 }
 
@@ -475,108 +511,225 @@
 	U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
 	U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
 	U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
+	U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
 	U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
 };
 
+static int boot_selected_os(int argc, char * const argv[], int state,
+		bootm_headers_t *images, boot_os_fn *boot_fn)
+{
+	if (images->os.type == IH_TYPE_STANDALONE) {
+		/* This may return when 'autostart' is 'no' */
+		bootm_start_standalone(argc, argv);
+		return 0;
+	}
+#ifdef CONFIG_SILENT_CONSOLE
+	if (images->os.os == IH_OS_LINUX)
+		fixup_silent_linux();
+#endif
+	arch_preboot_os();
+	boot_fn(state, argc, argv, images);
+	if (state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
+		return 0;
+	bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
+#ifdef DEBUG
+	puts("\n## Control returned to monitor - resetting...\n");
+#endif
+	return BOOTM_ERR_RESET;
+}
+
+/**
+ * Execute selected states of the bootm command.
+ *
+ * Note the arguments to this state must be the first argument, Any 'bootm'
+ * or sub-command arguments must have already been taken.
+ *
+ * Note that if states contains more than one flag it MUST contain
+ * BOOTM_STATE_START, since this handles and consumes the command line args.
+ *
+ * Also note that aside from boot_os_fn functions and bootm_load_os no other
+ * functions we store the return value of in 'ret' may use a negative return
+ * value, without special handling.
+ *
+ * @param cmdtp		Pointer to bootm command table entry
+ * @param flag		Command flags (CMD_FLAG_...)
+ * @param argc		Number of subcommand arguments (0 = no arguments)
+ * @param argv		Arguments
+ * @param states	Mask containing states to run (BOOTM_STATE_...)
+ * @param images	Image header information
+ * @param boot_progress 1 to show boot progress, 0 to not do this
+ * @return 0 if ok, something else on error. Some errors will cause this
+ *	function to perform a reboot! If states contains BOOTM_STATE_OS_GO
+ *	then the intent is to boot an OS, so this function will not return
+ *	unless the image type is standalone.
+ */
+static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc,
+		char * const argv[], int states, bootm_headers_t *images,
+		int boot_progress)
+{
+	boot_os_fn *boot_fn;
+	ulong iflag = 0;
+	int ret = 0;
+
+	images->state |= states;
+
+	/*
+	 * Work through the states and see how far we get. We stop on
+	 * any error.
+	 */
+	if (states & BOOTM_STATE_START)
+		ret = bootm_start(cmdtp, flag, argc, argv);
+
+	if (!ret && (states & BOOTM_STATE_FINDOS))
+		ret = bootm_find_os(cmdtp, flag, argc, argv);
+
+	if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
+		ret = bootm_find_other(cmdtp, flag, argc, argv);
+		argc = 0;	/* consume the args */
+	}
+
+	/*
+	 * We have reached the point of no return: we are going to
+	 * overwrite all exception vector code, so we cannot easily
+	 * recover from any failures any more...
+	 */
+	iflag = disable_interrupts();
+#ifdef CONFIG_NETCONSOLE
+	/* Stop the ethernet stack if NetConsole could have left it up */
+	eth_halt();
+#endif
+
+#if defined(CONFIG_CMD_USB)
+	/*
+	 * turn off USB to prevent the host controller from writing to the
+	 * SDRAM while Linux is booting. This could happen (at least for OHCI
+	 * controller), because the HCCA (Host Controller Communication Area)
+	 * lies within the SDRAM and the host controller writes continously to
+	 * this area (as busmaster!). The HccaFrameNumber is for example
+	 * updated every 1 ms within the HCCA structure in SDRAM! For more
+	 * details see the OpenHCI specification.
+	 */
+	usb_stop();
+#endif
+
+	/* Load the OS */
+	if (!ret && (states & BOOTM_STATE_LOADOS)) {
+		ulong load_end;
+
+		ret = bootm_load_os(images, &load_end, 0);
+		if (ret && ret != BOOTM_ERR_OVERLAP)
+			goto err;
+
+		if (ret == 0)
+			lmb_reserve(&images->lmb, images->os.load,
+				    (load_end - images->os.load));
+		else if (ret == BOOTM_ERR_OVERLAP)
+			ret = 0;
+	}
+
+	/* Relocate the ramdisk */
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+	if (!ret && (states & BOOTM_STATE_RAMDISK)) {
+		ulong rd_len = images->rd_end - images->rd_start;
+
+		ret = boot_ramdisk_high(&images->lmb, images->rd_start,
+			rd_len, &images->initrd_start, &images->initrd_end);
+		if (!ret) {
+			setenv_hex("initrd_start", images->initrd_start);
+			setenv_hex("initrd_end", images->initrd_end);
+		}
+	}
+#endif
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
+	if (!ret && (states & BOOTM_STATE_FDT)) {
+		boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
+		ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
+					&images->ft_len);
+	}
+#endif
+
+	/* From now on, we need the OS boot function */
+	if (ret)
+		return ret;
+	boot_fn = boot_os[images->os.os];
+	if (boot_fn == NULL) {
+		if (iflag)
+			enable_interrupts();
+		printf("ERROR: booting os '%s' (%d) is not supported\n",
+		       genimg_get_os_name(images->os.os), images->os.os);
+		bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
+		return 1;
+	}
+
+	/* Call various other states that are not generally used */
+	if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
+		ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
+	if (!ret && (states & BOOTM_STATE_OS_BD_T))
+		ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
+	if (!ret && (states & BOOTM_STATE_OS_PREP))
+		ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
+
+#ifdef CONFIG_TRACE
+	/* Pretend to run the OS, then run a user command */
+	if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
+		char *cmd_list = getenv("fakegocmd");
+
+		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
+				images, boot_fn);
+		if (!ret && cmd_list)
+			ret = run_command_list(cmd_list, -1, flag);
+	}
+#endif
+	/* Now run the OS! We hope this doesn't return */
+	if (!ret && (states & BOOTM_STATE_OS_GO)) {
+		ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
+				images, boot_fn);
+		if (ret)
+			goto err;
+	}
+
+	return ret;
+
+	/* Deal with any fallout */
+err:
+	if (iflag)
+		enable_interrupts();
+
+	if (ret == BOOTM_ERR_UNIMPLEMENTED)
+		bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
+	else if (ret == BOOTM_ERR_RESET)
+		do_reset(cmdtp, flag, argc, argv);
+	else
+		puts("subcommand not supported\n");
+
+	return ret;
+}
+
 static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
 			char * const argv[])
 {
 	int ret = 0;
 	long state;
 	cmd_tbl_t *c;
-	boot_os_fn *boot_fn;
 
-	c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+	c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+	argc--; argv++;
 
 	if (c) {
 		state = (long)c->cmd;
-
-		/* treat start special since it resets the state machine */
-		if (state == BOOTM_STATE_START) {
-			argc--;
-			argv++;
-			return bootm_start(cmdtp, flag, argc, argv);
-		}
+		if (state == BOOTM_STATE_START)
+			state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
 	} else {
 		/* Unrecognized command */
 		return CMD_RET_USAGE;
 	}
 
-	if (images.state < BOOTM_STATE_START ||
-	    images.state >= state) {
+	if (state != BOOTM_STATE_START && images.state >= state) {
 		printf("Trying to execute a command out of order\n");
 		return CMD_RET_USAGE;
 	}
 
-	images.state |= state;
-	boot_fn = boot_os[images.os.os];
-
-	switch (state) {
-		ulong load_end;
-		case BOOTM_STATE_START:
-			/* should never occur */
-			break;
-		case BOOTM_STATE_LOADOS:
-			ret = bootm_load_os(images.os, &load_end, 0);
-			if (ret)
-				return ret;
-
-			lmb_reserve(&images.lmb, images.os.load,
-					(load_end - images.os.load));
-			break;
-#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
-		case BOOTM_STATE_RAMDISK:
-		{
-			ulong rd_len = images.rd_end - images.rd_start;
-
-			ret = boot_ramdisk_high(&images.lmb, images.rd_start,
-				rd_len, &images.initrd_start, &images.initrd_end);
-			if (ret)
-				return ret;
-
-			setenv_hex("initrd_start", images.initrd_start);
-			setenv_hex("initrd_end", images.initrd_end);
-		}
-			break;
-#endif
-#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
-		case BOOTM_STATE_FDT:
-		{
-			boot_fdt_add_mem_rsv_regions(&images.lmb,
-						     images.ft_addr);
-			ret = boot_relocate_fdt(&images.lmb,
-				&images.ft_addr, &images.ft_len);
-			break;
-		}
-#endif
-		case BOOTM_STATE_OS_CMDLINE:
-			ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images);
-			if (ret)
-				printf("cmdline subcommand not supported\n");
-			break;
-		case BOOTM_STATE_OS_BD_T:
-			ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images);
-			if (ret)
-				printf("bdt subcommand not supported\n");
-			break;
-		case BOOTM_STATE_OS_PREP:
-			ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images);
-			if (ret)
-				printf("prep subcommand not supported\n");
-			break;
-		case BOOTM_STATE_OS_GO:
-			disable_interrupts();
-#ifdef CONFIG_NETCONSOLE
-			/*
-			 * Stop the ethernet stack if NetConsole could have
-			 * left it up
-			 */
-			eth_halt();
-#endif
-			arch_preboot_os();
-			boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
-			break;
-	}
+	ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
 
 	return ret;
 }
@@ -587,10 +740,6 @@
 
 int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	ulong		iflag;
-	ulong		load_end = 0;
-	int		ret;
-	boot_os_fn	*boot_fn;
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
 	static int relocated = 0;
 
@@ -611,11 +760,12 @@
 #endif
 
 	/* determine if we have a sub command */
-	if (argc > 1) {
+	argc--; argv++;
+	if (argc > 0) {
 		char *endp;
 
-		simple_strtoul(argv[1], &endp, 16);
-		/* endp pointing to NULL means that argv[1] was just a
+		simple_strtoul(argv[0], &endp, 16);
+		/* endp pointing to NULL means that argv[0] was just a
 		 * valid number, pass it along to the normal bootm processing
 		 *
 		 * If endp is ':' or '#' assume a FIT identifier so pass
@@ -627,101 +777,10 @@
 			return do_bootm_subcommand(cmdtp, flag, argc, argv);
 	}
 
-	if (bootm_start(cmdtp, flag, argc, argv))
-		return 1;
-
-	/*
-	 * We have reached the point of no return: we are going to
-	 * overwrite all exception vector code, so we cannot easily
-	 * recover from any failures any more...
-	 */
-	iflag = disable_interrupts();
-
-#ifdef CONFIG_NETCONSOLE
-	/* Stop the ethernet stack if NetConsole could have left it up */
-	eth_halt();
-#endif
-
-#if defined(CONFIG_CMD_USB)
-	/*
-	 * turn off USB to prevent the host controller from writing to the
-	 * SDRAM while Linux is booting. This could happen (at least for OHCI
-	 * controller), because the HCCA (Host Controller Communication Area)
-	 * lies within the SDRAM and the host controller writes continously to
-	 * this area (as busmaster!). The HccaFrameNumber is for example
-	 * updated every 1 ms within the HCCA structure in SDRAM! For more
-	 * details see the OpenHCI specification.
-	 */
-	usb_stop();
-#endif
-
-	ret = bootm_load_os(images.os, &load_end, 1);
-
-	if (ret < 0) {
-		if (ret == BOOTM_ERR_RESET)
-			do_reset(cmdtp, flag, argc, argv);
-		if (ret == BOOTM_ERR_OVERLAP) {
-			if (images.legacy_hdr_valid) {
-				image_header_t *hdr;
-				hdr = &images.legacy_hdr_os_copy;
-				if (image_get_type(hdr) == IH_TYPE_MULTI)
-					puts("WARNING: legacy format multi "
-						"component image "
-						"overwritten\n");
-			} else {
-				puts("ERROR: new format image overwritten - "
-					"must RESET the board to recover\n");
-				bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
-				do_reset(cmdtp, flag, argc, argv);
-			}
-		}
-		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
-			if (iflag)
-				enable_interrupts();
-			bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
-			return 1;
-		}
-	}
-
-	lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
-
-	if (images.os.type == IH_TYPE_STANDALONE) {
-		if (iflag)
-			enable_interrupts();
-		/* This may return when 'autostart' is 'no' */
-		bootm_start_standalone(iflag, argc, argv);
-		return 0;
-	}
-
-	bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS);
-
-#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
-	if (images.os.os == IH_OS_LINUX)
-		fixup_silent_linux();
-#endif
-
-	boot_fn = boot_os[images.os.os];
-
-	if (boot_fn == NULL) {
-		if (iflag)
-			enable_interrupts();
-		printf("ERROR: booting os '%s' (%d) is not supported\n",
-			genimg_get_os_name(images.os.os), images.os.os);
-		bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
-		return 1;
-	}
-
-	arch_preboot_os();
-
-	boot_fn(0, argc, argv, &images);
-
-	bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
-#ifdef DEBUG
-	puts("\n## Control returned to monitor - resetting...\n");
-#endif
-	do_reset(cmdtp, flag, argc, argv);
-
-	return 1;
+	return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
+		BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
+		BOOTM_STATE_LOADOS | BOOTM_STATE_OS_PREP |
+		BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO, &images, 1);
 }
 
 int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
@@ -816,22 +875,22 @@
 #endif
 
 	/* find out kernel image address */
-	if (argc < 2) {
+	if (argc < 1) {
 		img_addr = load_addr;
 		debug("*  kernel: default image load address = 0x%08lx\n",
 				load_addr);
 #if defined(CONFIG_FIT)
-	} else if (fit_parse_conf(argv[1], load_addr, &img_addr,
+	} else if (fit_parse_conf(argv[0], load_addr, &img_addr,
 							&fit_uname_config)) {
 		debug("*  kernel: config '%s' from image at 0x%08lx\n",
 				fit_uname_config, img_addr);
-	} else if (fit_parse_subimage(argv[1], load_addr, &img_addr,
+	} else if (fit_parse_subimage(argv[0], load_addr, &img_addr,
 							&fit_uname_kernel)) {
 		debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
 				fit_uname_kernel, img_addr);
 #endif
 	} else {
-		img_addr = simple_strtoul(argv[1], NULL, 16);
+		img_addr = simple_strtoul(argv[0], NULL, 16);
 		debug("*  kernel: cmdline image address = 0x%08lx\n", img_addr);
 	}
 
@@ -1346,6 +1405,19 @@
 }
 #endif /* CONFIG_SILENT_CONSOLE */
 
+#if defined(CONFIG_BOOTM_NETBSD) || defined(CONFIG_BOOTM_PLAN9)
+static void copy_args(char *dest, int argc, char * const argv[], char delim)
+{
+	int i;
+
+	for (i = 0; i < argc; i++) {
+		if (i > 0)
+			*dest++ = delim;
+		strcpy(dest, argv[i]);
+		dest += strlen(argv[i]);
+	}
+}
+#endif
 
 /*******************************************************************/
 /* OS booting routines */
@@ -1401,20 +1473,14 @@
 	consdev = "scc3";
 #endif
 
-	if (argc > 2) {
+	if (argc > 0) {
 		ulong len;
 		int   i;
 
-		for (i = 2, len = 0; i < argc; i += 1)
+		for (i = 0, len = 0; i < argc; i += 1)
 			len += strlen(argv[i]) + 1;
 		cmdline = malloc(len);
-
-		for (i = 2, len = 0; i < argc; i += 1) {
-			if (i > 2)
-				cmdline[len++] = ' ';
-			strcpy(&cmdline[len], argv[i]);
-			len += strlen(argv[i]);
-		}
+		copy_args(cmdline, argc, argv, ' ');
 	} else if ((cmdline = getenv("bootargs")) == NULL) {
 		cmdline = "";
 	}
@@ -1533,6 +1599,7 @@
 			   bootm_headers_t *images)
 {
 	void (*entry_point)(void);
+	char *s;
 
 	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
 		return 1;
@@ -1544,6 +1611,20 @@
 	}
 #endif
 
+	/* See README.plan9 */
+	s = getenv("confaddr");
+	if (s != NULL) {
+		char *confaddr = (char *)simple_strtoul(s, NULL, 16);
+
+		if (argc > 0) {
+			copy_args(confaddr, argc, argv, '\n');
+		} else {
+			s = getenv("bootargs");
+			if (s != NULL)
+				strcpy(confaddr, s);
+		}
+	}
+
 	entry_point = (void (*)(void))images->ep;
 
 	printf("## Transferring control to Plan 9 (at address %08lx) ...\n",
@@ -1663,9 +1744,8 @@
 	int ret;
 	void *zi_start, *zi_end;
 
-	memset(images, 0, sizeof(bootm_headers_t));
-
-	boot_start_lmb(images);
+	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
+			      images, 1);
 
 	/* Setup Linux kernel zImage entry point */
 	if (argc < 2) {
@@ -1684,73 +1764,25 @@
 
 	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
 
-	/* Find ramdisk */
-	ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
-			&images->rd_start, &images->rd_end);
-	if (ret) {
-		puts("Ramdisk image is corrupt or invalid\n");
-		return 1;
-	}
+	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_FINDOTHER,
+			      images, 1);
 
-#if defined(CONFIG_OF_LIBFDT)
-	/* find flattened device tree */
-	ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
-			   &images->ft_addr, &images->ft_len);
-	if (ret) {
-		puts("Could not find a valid device tree\n");
-		return 1;
-	}
-
-	set_working_fdt_addr(images->ft_addr);
-#endif
-
-	return 0;
+	return ret;
 }
 
-static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	bootm_headers_t	images;
+	int ret;
 
 	if (bootz_start(cmdtp, flag, argc, argv, &images))
 		return 1;
 
-	/*
-	 * We have reached the point of no return: we are going to
-	 * overwrite all exception vector code, so we cannot easily
-	 * recover from any failures any more...
-	 */
-	disable_interrupts();
+	ret = do_bootm_states(cmdtp, flag, argc, argv,
+			      BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO,
+			      &images, 1);
 
-#ifdef CONFIG_NETCONSOLE
-	/* Stop the ethernet stack if NetConsole could have left it up */
-	eth_halt();
-#endif
-
-#if defined(CONFIG_CMD_USB)
-	/*
-	 * turn off USB to prevent the host controller from writing to the
-	 * SDRAM while Linux is booting. This could happen (at least for OHCI
-	 * controller), because the HCCA (Host Controller Communication Area)
-	 * lies within the SDRAM and the host controller writes continously to
-	 * this area (as busmaster!). The HccaFrameNumber is for example
-	 * updated every 1 ms within the HCCA structure in SDRAM! For more
-	 * details see the OpenHCI specification.
-	 */
-	usb_stop();
-#endif
-
-#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
-	fixup_silent_linux();
-#endif
-	arch_preboot_os();
-
-	do_bootm_linux(0, argc, argv, &images);
-#ifdef DEBUG
-	puts("\n## Control returned to monitor - resetting...\n");
-#endif
-	do_reset(cmdtp, flag, argc, argv);
-
-	return 1;
+	return ret;
 }
 
 #ifdef CONFIG_SYS_LONGHELP
diff --git a/common/cmd_ide.c b/common/cmd_ide.c
index 78b4aa7..59e95df 100644
--- a/common/cmd_ide.c
+++ b/common/cmd_ide.c
@@ -830,7 +830,7 @@
 
 /* ------------------------------------------------------------------------- */
 
-ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer)
 {
 	ulong n = 0;
 	unsigned char c;
@@ -844,7 +844,7 @@
 		lba48 = 1;
 	}
 #endif
-	debug("ide_read dev %d start %lX, blocks " LBAF " buffer at %lX\n",
+	debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
 	      device, blknr, blkcnt, (ulong) buffer);
 
 	ide_led(DEVICE_LED(device), 1);	/* LED on       */
@@ -934,8 +934,8 @@
 
 		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
 		    ATA_STAT_DRQ) {
-			printf("Error (no IRQ) dev %d blk %ld: status %#02x\n",
-				device, blknr, c);
+			printf("Error (no IRQ) dev %d blk " LBAF ": status "
+			       "%#02x\n", device, blknr, c);
 			break;
 		}
 
@@ -954,7 +954,7 @@
 /* ------------------------------------------------------------------------- */
 
 
-ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer)
+ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt, const void *buffer)
 {
 	ulong n = 0;
 	unsigned char c;
@@ -1022,8 +1022,8 @@
 
 		if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
 		    ATA_STAT_DRQ) {
-			printf("Error (no IRQ) dev %d blk %ld: status %#02x\n",
-				device, blknr, c);
+			printf("Error (no IRQ) dev %d blk " LBAF ": status "
+				"%#02x\n", device, blknr, c);
 			goto WR_OUT;
 		}
 
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index 6df00b1..77eafa0 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -551,6 +551,8 @@
 			*cp++;
 	}
 	unmap_sysmem(buf);
+
+	return 0;
 }
 
 #ifdef CONFIG_LOOPW
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 7d82469..5f1ed43 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -147,6 +147,36 @@
 	"- display info of the current MMC device"
 );
 
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+	int err;
+	err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+	if ((err == 0) && (access != 0)) {
+		printf("\t\t\t!!!Notice!!!\n");
+
+		printf("!You must close EMMC boot Partition");
+		printf("after all images are written\n");
+
+		printf("!EMMC boot partition has continuity");
+		printf("at image writing time.\n");
+
+		printf("!So, do not close the boot partition");
+		printf("before all images are written.\n");
+		return 0;
+	} else if ((err == 0) && (access == 0))
+		return 0;
+	else if ((err != 0) && (access != 0)) {
+		printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+		return 1;
+	} else {
+		printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+		return 1;
+	}
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	enum mmc_state state;
@@ -258,8 +288,74 @@
 				curr_device, mmc->part_num);
 
 		return 0;
-	}
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	} else if ((strcmp(argv[1], "open") == 0) ||
+			(strcmp(argv[1], "close") == 0)) {
+		int dev;
+		struct mmc *mmc;
+		u8 part_num, access = 0;
 
+		if (argc == 4) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			part_num = simple_strtoul(argv[3], NULL, 10);
+		} else {
+			return CMD_RET_USAGE;
+		}
+
+		mmc = find_mmc_device(dev);
+		if (!mmc) {
+			printf("no mmc device at slot %x\n", dev);
+			return 1;
+		}
+
+		if (IS_SD(mmc)) {
+			printf("SD device cannot be opened/closed\n");
+			return 1;
+		}
+
+		if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
+			printf("Invalid boot partition number:\n");
+			printf("Boot partition number cannot be <= 0\n");
+			printf("EMMC44 supports only 2 boot partitions\n");
+			return 1;
+		}
+
+		if (strcmp(argv[1], "open") == 0)
+			access = part_num; /* enable R/W access to boot part*/
+		else
+			access = 0; /* No access to boot partition */
+
+		/* acknowledge to be sent during boot operation */
+		return boot_part_access(mmc, 1, part_num, access);
+
+	} else if (strcmp(argv[1], "bootpart") == 0) {
+		int dev;
+		dev = simple_strtoul(argv[2], NULL, 10);
+
+		u32 bootsize = simple_strtoul(argv[3], NULL, 10);
+		u32 rpmbsize = simple_strtoul(argv[4], NULL, 10);
+		struct mmc *mmc = find_mmc_device(dev);
+		if (!mmc) {
+			printf("no mmc device at slot %x\n", dev);
+			return 1;
+		}
+
+		if (IS_SD(mmc)) {
+			printf("It is not a EMMC device\n");
+			return 1;
+		}
+
+		if (0 == mmc_boot_partition_size_change(mmc,
+							bootsize, rpmbsize)) {
+			printf("EMMC boot partition Size %d MB\n", bootsize);
+			printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+			return 0;
+		} else {
+			printf("EMMC boot partition Size change Failed.\n");
+			return 1;
+		}
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+	}
 	state = MMC_INVALID;
 	if (argc == 5 && strcmp(argv[1], "read") == 0)
 		state = MMC_READ;
@@ -334,5 +430,14 @@
 	"mmc rescan\n"
 	"mmc part - lists available partition on current mmc device\n"
 	"mmc dev [dev] [part] - show or set current mmc device [partition]\n"
-	"mmc list - lists available devices");
+	"mmc list - lists available devices\n"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	"mmc open <dev> <boot_partition>\n"
+	" - Enable boot_part for booting and enable R/W access of boot_part\n"
+	"mmc close <dev> <boot_partition>\n"
+	" - Enable boot_part for booting and disable access to boot_part\n"
+	"mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
+	" - change sizes of boot and RPMB partions of specified device\n"
 #endif
+	);
+#endif /* !CONFIG_GENERIC_MMC */
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 2dbd49c..1fb75d8 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -26,12 +26,21 @@
 
 #define MAX_TFTP_PATH_LEN 127
 
+const char *pxe_default_paths[] = {
+#ifdef CONFIG_SYS_SOC
+	"default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC,
+#endif
+	"default-" CONFIG_SYS_ARCH,
+	"default",
+	NULL
+};
+
 /*
  * Like getenv, but prints an error if envvar isn't defined in the
  * environment.  It always returns what getenv does, so it can be used in
  * place of getenv without changing error handling otherwise.
  */
-static char *from_env(char *envvar)
+static char *from_env(const char *envvar)
 {
 	char *ret;
 
@@ -55,37 +64,21 @@
  */
 static int format_mac_pxe(char *outbuf, size_t outbuf_len)
 {
-	size_t ethaddr_len;
-	char *p, *ethaddr;
+	uchar ethaddr[6];
 
-	ethaddr = from_env("ethaddr");
-
-	if (!ethaddr)
-		return -ENOENT;
-
-	ethaddr_len = strlen(ethaddr);
-
-	/*
-	 * ethaddr_len + 4 gives room for "01-", ethaddr, and a NUL byte at
-	 * the end.
-	 */
-	if (outbuf_len < ethaddr_len + 4) {
-		printf("outbuf is too small (%d < %d)\n",
-				outbuf_len, ethaddr_len + 4);
+	if (outbuf_len < 21) {
+		printf("outbuf is too small (%d < 21)\n", outbuf_len);
 
 		return -EINVAL;
 	}
 
-	strcpy(outbuf, "01-");
+	if (!eth_getenv_enetaddr_by_index("eth", eth_get_dev_index(),
+					  ethaddr))
+		return -ENOENT;
 
-	for (p = outbuf + 3; *ethaddr; ethaddr++, p++) {
-		if (*ethaddr == ':')
-			*p = '-';
-		else
-			*p = tolower(*ethaddr);
-	}
-
-	*p = '\0';
+	sprintf(outbuf, "01-%02x-%02x-%02x-%02x-%02x-%02x",
+		ethaddr[0], ethaddr[1], ethaddr[2],
+		ethaddr[3], ethaddr[4], ethaddr[5]);
 
 	return 1;
 }
@@ -131,14 +124,14 @@
 	return 1;
 }
 
-static int (*do_getfile)(char *file_path, char *file_addr);
+static int (*do_getfile)(const char *file_path, char *file_addr);
 
-static int do_get_tftp(char *file_path, char *file_addr)
+static int do_get_tftp(const char *file_path, char *file_addr)
 {
 	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
 
 	tftp_argv[1] = file_addr;
-	tftp_argv[2] = file_path;
+	tftp_argv[2] = (void *)file_path;
 
 	if (do_tftpb(NULL, 0, 3, tftp_argv))
 		return -ENOENT;
@@ -148,12 +141,12 @@
 
 static char *fs_argv[5];
 
-static int do_get_ext2(char *file_path, char *file_addr)
+static int do_get_ext2(const char *file_path, char *file_addr)
 {
 #ifdef CONFIG_CMD_EXT2
 	fs_argv[0] = "ext2load";
 	fs_argv[3] = file_addr;
-	fs_argv[4] = file_path;
+	fs_argv[4] = (void *)file_path;
 
 	if (!do_ext2load(NULL, 0, 5, fs_argv))
 		return 1;
@@ -161,12 +154,12 @@
 	return -ENOENT;
 }
 
-static int do_get_fat(char *file_path, char *file_addr)
+static int do_get_fat(const char *file_path, char *file_addr)
 {
 #ifdef CONFIG_CMD_FAT
 	fs_argv[0] = "fatload";
 	fs_argv[3] = file_addr;
-	fs_argv[4] = file_path;
+	fs_argv[4] = (void *)file_path;
 
 	if (!do_fat_fsload(NULL, 0, 5, fs_argv))
 		return 1;
@@ -182,7 +175,7 @@
  *
  * Returns 1 for success, or < 0 on error.
  */
-static int get_relfile(char *file_path, void *file_addr)
+static int get_relfile(const char *file_path, void *file_addr)
 {
 	size_t path_len;
 	char relfile[MAX_TFTP_PATH_LEN+1];
@@ -221,7 +214,7 @@
  *
  * Returns 1 on success, or < 0 for error.
  */
-static int get_pxe_file(char *file_path, void *file_addr)
+static int get_pxe_file(const char *file_path, void *file_addr)
 {
 	unsigned long config_file_size;
 	char *tftp_filesize;
@@ -258,7 +251,7 @@
  *
  * Returns 1 on success or < 0 on error.
  */
-static int get_pxelinux_path(char *file, void *pxefile_addr_r)
+static int get_pxelinux_path(const char *file, void *pxefile_addr_r)
 {
 	size_t base_len = strlen(PXELINUX_DIR);
 	char path[MAX_TFTP_PATH_LEN+1];
@@ -355,7 +348,7 @@
 {
 	char *pxefile_addr_str;
 	unsigned long pxefile_addr_r;
-	int err;
+	int err, i = 0;
 
 	do_getfile = do_get_tftp;
 
@@ -376,16 +369,23 @@
 	 * Keep trying paths until we successfully get a file we're looking
 	 * for.
 	 */
-	if (pxe_uuid_path((void *)pxefile_addr_r) > 0
-		|| pxe_mac_path((void *)pxefile_addr_r) > 0
-		|| pxe_ipaddr_paths((void *)pxefile_addr_r) > 0
-		|| get_pxelinux_path("default", (void *)pxefile_addr_r) > 0) {
-
+	if (pxe_uuid_path((void *)pxefile_addr_r) > 0 ||
+	    pxe_mac_path((void *)pxefile_addr_r) > 0 ||
+	    pxe_ipaddr_paths((void *)pxefile_addr_r) > 0) {
 		printf("Config file found\n");
 
 		return 0;
 	}
 
+	while (pxe_default_paths[i]) {
+		if (get_pxelinux_path(pxe_default_paths[i],
+				      (void *)pxefile_addr_r) > 0) {
+			printf("Config file found\n");
+			return 0;
+		}
+		i++;
+	}
+
 	printf("Config file not found\n");
 
 	return 1;
@@ -398,7 +398,7 @@
  *
  * Returns 1 on success or < 0 on error.
  */
-static int get_relfile_envaddr(char *file_path, char *envaddr_name)
+static int get_relfile_envaddr(const char *file_path, const char *envaddr_name)
 {
 	unsigned long file_addr;
 	char *envaddr;
@@ -445,14 +445,17 @@
  * list - lets these form a list, which a pxe_menu struct will hold.
  */
 struct pxe_label {
+	char num[4];
 	char *name;
 	char *menu;
 	char *kernel;
 	char *append;
 	char *initrd;
 	char *fdt;
+	int ipappend;
 	int attempted;
 	int localboot;
+	int localboot_val;
 	struct list_head list;
 };
 
@@ -533,21 +536,9 @@
 static void label_print(void *data)
 {
 	struct pxe_label *label = data;
-	const char *c = label->menu ? label->menu : label->kernel;
+	const char *c = label->menu ? label->menu : label->name;
 
-	printf("%s:\t%s\n", label->name, c);
-
-	if (label->kernel)
-		printf("\t\tkernel: %s\n", label->kernel);
-
-	if (label->append)
-		printf("\t\tappend: %s\n", label->append);
-
-	if (label->initrd)
-		printf("\t\tinitrd: %s\n", label->initrd);
-
-	if (label->fdt)
-		printf("\tfdt: %s\n", label->fdt);
+	printf("%s:\t%s\n", label->num, c);
 }
 
 /*
@@ -591,34 +582,43 @@
  * If the label specifies an 'append' line, its contents will overwrite that
  * of the 'bootargs' environment variable.
  */
-static void label_boot(struct pxe_label *label)
+static int label_boot(struct pxe_label *label)
 {
 	char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
+	char initrd_str[22];
+	char mac_str[29] = "";
+	char ip_str[68] = "";
+	char *bootargs;
 	int bootm_argc = 3;
+	int len = 0;
 
 	label_print(label);
 
 	label->attempted = 1;
 
 	if (label->localboot) {
-		label_localboot(label);
-		return;
+		if (label->localboot_val >= 0)
+			label_localboot(label);
+		return 0;
 	}
 
 	if (label->kernel == NULL) {
 		printf("No kernel given, skipping %s\n",
 				label->name);
-		return;
+		return 1;
 	}
 
 	if (label->initrd) {
 		if (get_relfile_envaddr(label->initrd, "ramdisk_addr_r") < 0) {
 			printf("Skipping %s for failure retrieving initrd\n",
 					label->name);
-			return;
+			return 1;
 		}
 
-		bootm_argv[2] = getenv("ramdisk_addr_r");
+		bootm_argv[2] = initrd_str;
+		strcpy(bootm_argv[2], getenv("ramdisk_addr_r"));
+		strcat(bootm_argv[2], ":");
+		strcat(bootm_argv[2], getenv("filesize"));
 	} else {
 		bootm_argv[2] = "-";
 	}
@@ -626,11 +626,43 @@
 	if (get_relfile_envaddr(label->kernel, "kernel_addr_r") < 0) {
 		printf("Skipping %s for failure retrieving kernel\n",
 				label->name);
-		return;
+		return 1;
+	}
+
+	if (label->ipappend & 0x1) {
+		sprintf(ip_str, " ip=%s:%s:%s:%s",
+			getenv("ipaddr"), getenv("serverip"),
+			getenv("gatewayip"), getenv("netmask"));
+		len += strlen(ip_str);
+	}
+
+	if (label->ipappend & 0x2) {
+		int err;
+		strcpy(mac_str, " BOOTIF=");
+		err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
+		if (err < 0)
+			mac_str[0] = '\0';
+		len += strlen(mac_str);
 	}
 
 	if (label->append)
-		setenv("bootargs", label->append);
+		len += strlen(label->append);
+
+	if (len) {
+		bootargs = malloc(len + 1);
+		if (!bootargs)
+			return 1;
+		bootargs[0] = '\0';
+		if (label->append)
+			strcpy(bootargs, label->append);
+		strcat(bootargs, ip_str);
+		strcat(bootargs, mac_str);
+
+		setenv("bootargs", bootargs);
+		printf("append: %s\n", bootargs);
+
+		free(bootargs);
+	}
 
 	bootm_argv[1] = getenv("kernel_addr_r");
 
@@ -654,7 +686,7 @@
 		if (get_relfile_envaddr(label->fdt, "fdt_addr_r") < 0) {
 			printf("Skipping %s for failure retrieving fdt\n",
 					label->name);
-			return;
+			return 1;
 		}
 	} else
 		bootm_argv[3] = getenv("fdt_addr");
@@ -663,6 +695,12 @@
 		bootm_argc = 4;
 
 	do_bootm(NULL, 0, bootm_argc, bootm_argv);
+
+#ifdef CONFIG_CMD_BOOTZ
+	/* Try booting a zImage if do_bootm returns */
+	do_bootz(NULL, 0, bootm_argc, bootm_argv);
+#endif
+	return 1;
 }
 
 /*
@@ -685,6 +723,8 @@
 	T_PROMPT,
 	T_INCLUDE,
 	T_FDT,
+	T_ONTIMEOUT,
+	T_IPAPPEND,
 	T_INVALID
 };
 
@@ -713,6 +753,8 @@
 	{"initrd", T_INITRD},
 	{"include", T_INCLUDE},
 	{"fdt", T_FDT},
+	{"ontimeout", T_ONTIMEOUT,},
+	{"ipappend", T_IPAPPEND,},
 	{NULL, T_INVALID}
 };
 
@@ -903,7 +945,6 @@
 {
 	struct token t;
 	char *s = *c;
-	unsigned long temp;
 
 	get_token(c, &t, L_SLITERAL);
 
@@ -912,12 +953,7 @@
 		return -EINVAL;
 	}
 
-	if (strict_strtoul(t.val, 10, &temp) < 0) {
-		printf("Expected unsigned integer: %s\n", t.val);
-		return -EINVAL;
-	}
-
-	*dst = (int)temp;
+	*dst = simple_strtol(t.val, NULL, 10);
 
 	free(t.val);
 
@@ -1016,10 +1052,8 @@
 
 	switch (t.type) {
 	case T_DEFAULT:
-		if (cfg->default_label)
-			free(cfg->default_label);
-
-		cfg->default_label = strdup(label->name);
+		if (!cfg->default_label)
+			cfg->default_label = strdup(label->name);
 
 		if (!cfg->default_label)
 			return -ENOMEM;
@@ -1108,7 +1142,12 @@
 			break;
 
 		case T_LOCALBOOT:
-			err = parse_integer(c, &label->localboot);
+			label->localboot = 1;
+			err = parse_integer(c, &label->localboot_val);
+			break;
+
+		case T_IPAPPEND:
+			err = parse_integer(c, &label->ipappend);
 			break;
 
 		case T_EOL:
@@ -1164,6 +1203,7 @@
 		err = 0;
 		switch (t.type) {
 		case T_MENU:
+			cfg->prompt = 1;
 			err = parse_menu(&p, cfg, b, nest_level);
 			break;
 
@@ -1176,6 +1216,7 @@
 			break;
 
 		case T_DEFAULT:
+		case T_ONTIMEOUT:
 			err = parse_sliteral(&p, &label_name);
 
 			if (label_name) {
@@ -1193,7 +1234,7 @@
 			break;
 
 		case T_PROMPT:
-			err = parse_integer(&p, &cfg->prompt);
+			eol_or_eof(&p);
 			break;
 
 		case T_EOL:
@@ -1276,6 +1317,8 @@
 	struct list_head *pos;
 	struct menu *m;
 	int err;
+	int i = 1;
+	char *default_num = NULL;
 
 	/*
 	 * Create a menu and add items for all the labels.
@@ -1289,18 +1332,23 @@
 	list_for_each(pos, &cfg->labels) {
 		label = list_entry(pos, struct pxe_label, list);
 
-		if (menu_item_add(m, label->name, label) != 1) {
+		sprintf(label->num, "%d", i++);
+		if (menu_item_add(m, label->num, label) != 1) {
 			menu_destroy(m);
 			return NULL;
 		}
+		if (cfg->default_label &&
+		    (strcmp(label->name, cfg->default_label) == 0))
+			default_num = label->num;
+
 	}
 
 	/*
 	 * After we've created items for each label in the menu, set the
 	 * menu's default label if one was specified.
 	 */
-	if (cfg->default_label) {
-		err = menu_default_set(m, cfg->default_label);
+	if (default_num) {
+		err = menu_default_set(m, default_num);
 		if (err != 1) {
 			if (err != -ENOENT) {
 				menu_destroy(m);
@@ -1367,10 +1415,13 @@
 	 * we give up.
 	 */
 
-	if (err == 1)
-		label_boot(choice);
-	else if (err != -ENOENT)
+	if (err == 1) {
+		err = label_boot(choice);
+		if (!err)
+			return;
+	} else if (err != -ENOENT) {
 		return;
+	}
 
 	boot_unattempted_labels(cfg);
 }
diff --git a/common/cmd_trace.c b/common/cmd_trace.c
new file mode 100644
index 0000000..ec3137a
--- /dev/null
+++ b/common/cmd_trace.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * 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 <command.h>
+#include <trace.h>
+#include <asm/io.h>
+
+static int get_args(int argc, char * const argv[], char **buff,
+		    size_t *buff_ptr, size_t *buff_size)
+{
+	if (argc < 2)
+		return -1;
+	if (argc < 4) {
+		*buff_size = getenv_ulong("profsize", 16, 0);
+		*buff = map_sysmem(getenv_ulong("profbase", 16, 0),
+				   *buff_size);
+		*buff_ptr = getenv_ulong("profoffset", 16, 0);
+	} else {
+		*buff_size = simple_strtoul(argv[3], NULL, 16);
+		*buff = map_sysmem(simple_strtoul(argv[2], NULL, 16),
+				   *buff_size);
+		*buff_ptr = 0;
+	};
+	return 0;
+}
+
+static int create_func_list(int argc, char * const argv[])
+{
+	size_t buff_size, avail, buff_ptr, used;
+	unsigned int needed;
+	char *buff;
+	int err;
+
+	if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
+		return -1;
+
+	avail = buff_size - buff_ptr;
+	err = trace_list_functions(buff + buff_ptr, avail, &needed);
+	if (err)
+		printf("Error: truncated (%#x bytes needed)\n", needed);
+	used = min(avail, needed);
+	printf("Function trace dumped to %08lx, size %#zx\n",
+	       (ulong)map_to_sysmem(buff + buff_ptr), used);
+	setenv_hex("profbase", map_to_sysmem(buff));
+	setenv_hex("profsize", buff_size);
+	setenv_hex("profoffset", buff_ptr + used);
+
+	return 0;
+}
+
+static int create_call_list(int argc, char * const argv[])
+{
+	size_t buff_size, avail, buff_ptr, used;
+	unsigned int needed;
+	char *buff;
+	int err;
+
+	if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
+		return -1;
+
+	avail = buff_size - buff_ptr;
+	err = trace_list_calls(buff + buff_ptr, avail, &needed);
+	if (err)
+		printf("Error: truncated (%#x bytes needed)\n", needed);
+	used = min(avail, needed);
+	printf("Call list dumped to %08lx, size %#zx\n",
+	       (ulong)map_to_sysmem(buff + buff_ptr), used);
+
+	setenv_hex("profbase", map_to_sysmem(buff));
+	setenv_hex("profsize", buff_size);
+	setenv_hex("profoffset", buff_ptr + used);
+
+	return 0;
+}
+
+int do_trace(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const char *cmd = argc < 2 ? NULL : argv[1];
+
+	if (!cmd)
+		return cmd_usage(cmdtp);
+	switch (*cmd) {
+	case 'p':
+		trace_set_enabled(0);
+		break;
+	case 'c':
+		if (create_call_list(argc, argv))
+			return cmd_usage(cmdtp);
+		break;
+	case 'r':
+		trace_set_enabled(1);
+		break;
+	case 'f':
+		if (create_func_list(argc, argv))
+			return cmd_usage(cmdtp);
+		break;
+	case 's':
+		trace_print_stats();
+		break;
+	default:
+		return CMD_RET_USAGE;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	trace,	4,	1,	do_trace,
+	"trace utility commands",
+	"stats                        - display tracing statistics\n"
+	"trace pause                        - pause tracing\n"
+	"trace resume                       - resume tracing\n"
+	"trace funclist [<addr> <size>]     - dump function list into buffer\n"
+	"trace calls  [<addr> <size>]       "
+		"- dump function call trace into buffer"
+);
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 0d421d9..d99f444 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -248,13 +248,16 @@
 	ulong		default_addr;
 	int		fdt_noffset;
 #endif
+	const char *select = NULL;
 
 	*of_flat_tree = NULL;
 	*of_size = 0;
 
-	if (argc > 3 || genimg_has_config(images)) {
+	if (argc > 2)
+		select = argv[2];
+	if (select || genimg_has_config(images)) {
 #if defined(CONFIG_FIT)
-		if (argc > 3) {
+		if (select) {
 			/*
 			 * If the FDT blob comes from the FIT image and the
 			 * FIT image address is omitted in the command line
@@ -268,18 +271,18 @@
 			else
 				default_addr = load_addr;
 
-			if (fit_parse_conf(argv[3], default_addr,
+			if (fit_parse_conf(select, default_addr,
 					   &fdt_addr, &fit_uname_config)) {
 				debug("*  fdt: config '%s' from image at 0x%08lx\n",
 				      fit_uname_config, fdt_addr);
-			} else if (fit_parse_subimage(argv[3], default_addr,
+			} else if (fit_parse_subimage(select, default_addr,
 				   &fdt_addr, &fit_uname_fdt)) {
 				debug("*  fdt: subimage '%s' from image at 0x%08lx\n",
 				      fit_uname_fdt, fdt_addr);
 			} else
 #endif
 			{
-				fdt_addr = simple_strtoul(argv[3], NULL, 16);
+				fdt_addr = simple_strtoul(select, NULL, 16);
 				debug("*  fdt: cmdline image address = 0x%08lx\n",
 				      fdt_addr);
 			}
diff --git a/common/image-fit.c b/common/image-fit.c
index f40f160..b75e119 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -234,42 +234,45 @@
  * @fit: pointer to the FIT format image header
  * @noffset: offset of the hash node
  * @p: pointer to prefix string
+ * @type: Type of information to print ("hash" or "sign")
  *
  * fit_image_print_data() lists properies for the processed hash node
  *
+ * This function avoid using puts() since it prints a newline on the host
+ * but does not in U-Boot.
+ *
  * returns:
  *     no returned results
  */
-static void fit_image_print_data(const void *fit, int noffset, const char *p)
+static void fit_image_print_data(const void *fit, int noffset, const char *p,
+				 const char *type)
 {
-	char *algo;
+	const char *keyname;
 	uint8_t *value;
 	int value_len;
-	int i, ret;
+	char *algo;
+	int required;
+	int ret, i;
 
-	/*
-	 * Check subnode name, must be equal to "hash".
-	 * Multiple hash nodes require unique unit node
-	 * names, e.g. hash@1, hash@2, etc.
-	 */
-	if (strncmp(fit_get_name(fit, noffset, NULL),
-		    FIT_HASH_NODENAME,
-		    strlen(FIT_HASH_NODENAME)) != 0)
-		return;
-
-	debug("%s  Hash node:    '%s'\n", p,
+	debug("%s  %s node:    '%s'\n", p, type,
 	      fit_get_name(fit, noffset, NULL));
-
-	printf("%s  Hash algo:    ", p);
+	printf("%s  %s algo:    ", p, type);
 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
 		printf("invalid/unsupported\n");
 		return;
 	}
-	printf("%s\n", algo);
+	printf("%s", algo);
+	keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
+	if (keyname)
+		printf(":%s", keyname);
+	if (required)
+		printf(" (required)");
+	printf("\n");
 
 	ret = fit_image_hash_get_value(fit, noffset, &value,
 					&value_len);
-	printf("%s  Hash value:   ", p);
+	printf("%s  %s value:   ", p, type);
 	if (ret) {
 		printf("unavailable\n");
 	} else {
@@ -278,7 +281,18 @@
 		printf("\n");
 	}
 
-	debug("%s  Hash len:     %d\n", p, value_len);
+	debug("%s  %s len:     %d\n", p, type, value_len);
+
+	/* Signatures have a time stamp */
+	if (IMAGE_ENABLE_TIMESTAMP && keyname) {
+		time_t timestamp;
+
+		printf("%s  Timestamp:    ", p);
+		if (fit_get_timestamp(fit, noffset, &timestamp))
+			printf("unavailable\n");
+		else
+			genimg_print_time(timestamp);
+	}
 }
 
 /**
@@ -303,8 +317,12 @@
 	 * names, e.g. hash@1, hash@2, signature@1, signature@2, etc.
 	 */
 	name = fit_get_name(fit, noffset, NULL);
-	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
-		fit_image_print_data(fit, noffset, p);
+	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
+		fit_image_print_data(fit, noffset, p, "Hash");
+	} else if (!strncmp(name, FIT_SIG_NODENAME,
+				strlen(FIT_SIG_NODENAME))) {
+		fit_image_print_data(fit, noffset, p, "Sign");
+	}
 }
 
 /**
@@ -944,13 +962,23 @@
 {
 	const void	*data;
 	size_t		size;
-	int		noffset;
+	int		noffset = 0;
 	char		*err_msg = "";
+	int verify_all = 1;
+	int ret;
 
 	/* Get image data and data length */
 	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
 		err_msg = "Can't get image data/size";
-		return 0;
+		goto error;
+	}
+
+	/* Verify all required signatures */
+	if (IMAGE_ENABLE_VERIFY &&
+	    fit_image_verify_required_sigs(fit, image_noffset, data, size,
+					   gd_fdt_blob(), &verify_all)) {
+		err_msg = "Unable to verify required signature";
+		goto error;
 	}
 
 	/* Process all hash subnodes of the component image node */
@@ -970,6 +998,15 @@
 						 &err_msg))
 				goto error;
 			puts("+ ");
+		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
+				!strncmp(name, FIT_SIG_NODENAME,
+					strlen(FIT_SIG_NODENAME))) {
+			ret = fit_image_check_sig(fit, noffset, data,
+							size, -1, &err_msg);
+			if (ret)
+				puts("- ");
+			else
+				puts("+ ");
 		}
 	}
 
diff --git a/common/image-sig.c b/common/image-sig.c
new file mode 100644
index 0000000..5d907cf
--- /dev/null
+++ b/common/image-sig.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2013, Google 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
+ */
+
+#ifdef USE_HOSTCC
+#include "mkimage.h"
+#include <time.h>
+#else
+#include <common.h>
+#include <malloc.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif /* !USE_HOSTCC*/
+#include <image.h>
+#include <rsa.h>
+
+#define IMAGE_MAX_HASHED_NODES		100
+
+struct image_sig_algo image_sig_algos[] = {
+	{
+		"sha1,rsa2048",
+		rsa_sign,
+		rsa_add_verify_data,
+		rsa_verify,
+	}
+};
+
+struct image_sig_algo *image_get_sig_algo(const char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
+		if (!strcmp(image_sig_algos[i].name, name))
+			return &image_sig_algos[i];
+	}
+
+	return NULL;
+}
+
+/**
+ * fit_region_make_list() - Make a list of image regions
+ *
+ * Given a list of fdt_regions, create a list of image_regions. This is a
+ * simple conversion routine since the FDT and image code use different
+ * structures.
+ *
+ * @fit: FIT image
+ * @fdt_regions: Pointer to FDT regions
+ * @count: Number of FDT regions
+ * @region: Pointer to image regions, which must hold @count records. If
+ * region is NULL, then (except for an SPL build) the array will be
+ * allocated.
+ * @return: Pointer to image regions
+ */
+struct image_region *fit_region_make_list(const void *fit,
+		struct fdt_region *fdt_regions, int count,
+		struct image_region *region)
+{
+	int i;
+
+	debug("Hash regions:\n");
+	debug("%10s %10s\n", "Offset", "Size");
+
+	/*
+	 * Use malloc() except in SPL (to save code size). In SPL the caller
+	 * must allocate the array.
+	 */
+#ifndef CONFIG_SPL_BUILD
+	if (!region)
+		region = calloc(sizeof(*region), count);
+#endif
+	if (!region)
+		return NULL;
+	for (i = 0; i < count; i++) {
+		debug("%10x %10x\n", fdt_regions[i].offset,
+		      fdt_regions[i].size);
+		region[i].data = fit + fdt_regions[i].offset;
+		region[i].size = fdt_regions[i].size;
+	}
+
+	return region;
+}
+
+static int fit_image_setup_verify(struct image_sign_info *info,
+		const void *fit, int noffset, int required_keynode,
+		char **err_msgp)
+{
+	char *algo_name;
+
+	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+		*err_msgp = "Can't get hash algo property";
+		return -1;
+	}
+	memset(info, '\0', sizeof(*info));
+	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	info->fit = (void *)fit;
+	info->node_offset = noffset;
+	info->algo = image_get_sig_algo(algo_name);
+	info->fdt_blob = gd_fdt_blob();
+	info->required_keynode = required_keynode;
+	printf("%s:%s", algo_name, info->keyname);
+
+	if (!info->algo) {
+		*err_msgp = "Unknown signature algorithm";
+		return -1;
+	}
+
+	return 0;
+}
+
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+		size_t size, int required_keynode, char **err_msgp)
+{
+	struct image_sign_info info;
+	struct image_region region;
+	uint8_t *fit_value;
+	int fit_value_len;
+
+	*err_msgp = NULL;
+	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+				   err_msgp))
+		return -1;
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+				     &fit_value_len)) {
+		*err_msgp = "Can't get hash value property";
+		return -1;
+	}
+
+	region.data = data;
+	region.size = size;
+
+	if (info.algo->verify(&info, &region, 1, fit_value, fit_value_len)) {
+		*err_msgp = "Verification failed";
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_image_verify_sig(const void *fit, int image_noffset,
+		const char *data, size_t size, const void *sig_blob,
+		int sig_offset)
+{
+	int noffset;
+	char *err_msg = "";
+	int verified = 0;
+	int ret;
+
+	/* Process all hash subnodes of the component image node */
+	for (noffset = fdt_first_subnode(fit, image_noffset);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(fit, noffset)) {
+		const char *name = fit_get_name(fit, noffset, NULL);
+
+		if (!strncmp(name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_image_check_sig(fit, noffset, data,
+							size, -1, &err_msg);
+			if (ret) {
+				puts("- ");
+			} else {
+				puts("+ ");
+				verified = 1;
+				break;
+			}
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = "Corrupted or truncated tree";
+		goto error;
+	}
+
+	return verified ? 0 : -EPERM;
+
+error:
+	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
+	       err_msg, fit_get_name(fit, noffset, NULL),
+	       fit_get_name(fit, image_noffset, NULL));
+	return -1;
+}
+
+int fit_image_verify_required_sigs(const void *fit, int image_noffset,
+		const char *data, size_t size, const void *sig_blob,
+		int *no_sigsp)
+{
+	int verify_count = 0;
+	int noffset;
+	int sig_node;
+
+	/* Work out what we need to verify */
+	*no_sigsp = 1;
+	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found: %s\n", __func__,
+		      fdt_strerror(sig_node));
+		return 0;
+	}
+
+	for (noffset = fdt_first_subnode(sig_blob, sig_node);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(sig_blob, noffset)) {
+		const char *required;
+		int ret;
+
+		required = fdt_getprop(sig_blob, noffset, "required", NULL);
+		if (!required || strcmp(required, "image"))
+			continue;
+		ret = fit_image_verify_sig(fit, image_noffset, data, size,
+					sig_blob, noffset);
+		if (ret) {
+			printf("Failed to verify required signature '%s'\n",
+			       fit_get_name(sig_blob, noffset, NULL));
+			return ret;
+		}
+		verify_count++;
+	}
+
+	if (verify_count)
+		*no_sigsp = 0;
+
+	return 0;
+}
+
+int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
+			 char **err_msgp)
+{
+	char * const exc_prop[] = {"data"};
+	const char *prop, *end, *name;
+	struct image_sign_info info;
+	const uint32_t *strings;
+	uint8_t *fit_value;
+	int fit_value_len;
+	int max_regions;
+	int i, prop_len;
+	char path[200];
+	int count;
+
+	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
+	      fit_get_name(fit, noffset, NULL),
+	      fit_get_name(gd_fdt_blob(), required_keynode, NULL));
+	*err_msgp = NULL;
+	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+				   err_msgp))
+		return -1;
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+				     &fit_value_len)) {
+		*err_msgp = "Can't get hash value property";
+		return -1;
+	}
+
+	/* Count the number of strings in the property */
+	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
+	end = prop ? prop + prop_len : prop;
+	for (name = prop, count = 0; name < end; name++)
+		if (!*name)
+			count++;
+	if (!count) {
+		*err_msgp = "Can't get hashed-nodes property";
+		return -1;
+	}
+
+	/* Add a sanity check here since we are using the stack */
+	if (count > IMAGE_MAX_HASHED_NODES) {
+		*err_msgp = "Number of hashed nodes exceeds maximum";
+		return -1;
+	}
+
+	/* Create a list of node names from those strings */
+	char *node_inc[count];
+
+	debug("Hash nodes (%d):\n", count);
+	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
+		debug("   '%s'\n", name);
+		node_inc[i] = (char *)name;
+	}
+
+	/*
+	 * Each node can generate one region for each sub-node. Allow for
+	 * 7 sub-nodes (hash@1, signature@1, etc.) and some extra.
+	 */
+	max_regions = 20 + count * 7;
+	struct fdt_region fdt_regions[max_regions];
+
+	/* Get a list of regions to hash */
+	count = fdt_find_regions(fit, node_inc, count,
+			exc_prop, ARRAY_SIZE(exc_prop),
+			fdt_regions, max_regions - 1,
+			path, sizeof(path), 0);
+	if (count < 0) {
+		*err_msgp = "Failed to hash configuration";
+		return -1;
+	}
+	if (count == 0) {
+		*err_msgp = "No data to hash";
+		return -1;
+	}
+	if (count >= max_regions - 1) {
+		*err_msgp = "Too many hash regions";
+		return -1;
+	}
+
+	/* Add the strings */
+	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
+	if (strings) {
+		fdt_regions[count].offset = fdt_off_dt_strings(fit) +
+				fdt32_to_cpu(strings[0]);
+		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
+		count++;
+	}
+
+	/* Allocate the region list on the stack */
+	struct image_region region[count];
+
+	fit_region_make_list(fit, fdt_regions, count, region);
+	if (info.algo->verify(&info, region, count, fit_value,
+			      fit_value_len)) {
+		*err_msgp = "Verification failed";
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_config_verify_sig(const void *fit, int conf_noffset,
+		const void *sig_blob, int sig_offset)
+{
+	int noffset;
+	char *err_msg = "";
+	int verified = 0;
+	int ret;
+
+	/* Process all hash subnodes of the component conf node */
+	for (noffset = fdt_first_subnode(fit, conf_noffset);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(fit, noffset)) {
+		const char *name = fit_get_name(fit, noffset, NULL);
+
+		if (!strncmp(name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_config_check_sig(fit, noffset, sig_offset,
+						   &err_msg);
+			if (ret) {
+				puts("- ");
+			} else {
+				puts("+ ");
+				verified = 1;
+				break;
+			}
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = "Corrupted or truncated tree";
+		goto error;
+	}
+
+	return verified ? 0 : -EPERM;
+
+error:
+	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
+	       err_msg, fit_get_name(fit, noffset, NULL),
+	       fit_get_name(fit, conf_noffset, NULL));
+	return -1;
+}
+
+int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
+		const void *sig_blob)
+{
+	int noffset;
+	int sig_node;
+
+	/* Work out what we need to verify */
+	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found: %s\n", __func__,
+		      fdt_strerror(sig_node));
+		return 0;
+	}
+
+	for (noffset = fdt_first_subnode(sig_blob, sig_node);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(sig_blob, noffset)) {
+		const char *required;
+		int ret;
+
+		required = fdt_getprop(sig_blob, noffset, "required", NULL);
+		if (!required || strcmp(required, "conf"))
+			continue;
+		ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
+					    noffset);
+		if (ret) {
+			printf("Failed to verify required signature '%s'\n",
+			       fit_get_name(sig_blob, noffset, NULL));
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int fit_config_verify(const void *fit, int conf_noffset)
+{
+	return !fit_config_verify_required_sigs(fit, conf_noffset,
+						gd_fdt_blob());
+}
diff --git a/common/image.c b/common/image.c
index f863502..1be384f 100644
--- a/common/image.c
+++ b/common/image.c
@@ -816,20 +816,23 @@
 	ulong		default_addr;
 	int		rd_noffset;
 #endif
+	const char *select = NULL;
 
 	*rd_start = 0;
 	*rd_end = 0;
 
+	if (argc >= 2)
+		select = argv[1];
 	/*
 	 * Look for a '-' which indicates to ignore the
 	 * ramdisk argument
 	 */
-	if ((argc >= 3) && (strcmp(argv[2], "-") ==  0)) {
+	if (select && strcmp(select, "-") ==  0) {
 		debug("## Skipping init Ramdisk\n");
 		rd_len = rd_data = 0;
-	} else if (argc >= 3 || genimg_has_config(images)) {
+	} else if (select || genimg_has_config(images)) {
 #if defined(CONFIG_FIT)
-		if (argc >= 3) {
+		if (select) {
 			/*
 			 * If the init ramdisk comes from the FIT image and
 			 * the FIT image address is omitted in the command
@@ -841,12 +844,12 @@
 			else
 				default_addr = load_addr;
 
-			if (fit_parse_conf(argv[2], default_addr,
-						&rd_addr, &fit_uname_config)) {
+			if (fit_parse_conf(select, default_addr,
+					   &rd_addr, &fit_uname_config)) {
 				debug("*  ramdisk: config '%s' from image at "
 						"0x%08lx\n",
 						fit_uname_config, rd_addr);
-			} else if (fit_parse_subimage(argv[2], default_addr,
+			} else if (fit_parse_subimage(select, default_addr,
 						&rd_addr, &fit_uname_ramdisk)) {
 				debug("*  ramdisk: subimage '%s' from image at "
 						"0x%08lx\n",
@@ -854,7 +857,7 @@
 			} else
 #endif
 			{
-				rd_addr = simple_strtoul(argv[2], NULL, 16);
+				rd_addr = simple_strtoul(select, NULL, 16);
 				debug("*  ramdisk: cmdline image address = "
 						"0x%08lx\n",
 						rd_addr);
@@ -918,7 +921,10 @@
 #endif
 		default:
 #ifdef CONFIG_SUPPORT_RAW_INITRD
-			if (argc >= 3 && (end = strchr(argv[2], ':'))) {
+			end = NULL;
+			if (select)
+				end = strchr(select, ':');
+			if (end) {
 				rd_len = simple_strtoul(++end, NULL, 16);
 				rd_data = rd_addr;
 			} else
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 457970f..4599d03 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -170,9 +170,9 @@
 		      block_dev_desc_t *dev_desc);
 int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
 		      struct us_data *ss);
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
 			    lbaint_t blkcnt, void *buffer);
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
 			     lbaint_t blkcnt, const void *buffer);
 struct usb_device * usb_get_dev_index(int index);
 void uhci_show_temp_int_td(void);
@@ -1054,7 +1054,7 @@
 }
 #endif /* CONFIG_USB_BIN_FIXUP */
 
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
 			    lbaint_t blkcnt, void *buffer)
 {
 	lbaint_t start, blks;
@@ -1127,7 +1127,7 @@
 	return blkcnt;
 }
 
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
 				lbaint_t blkcnt, const void *buffer)
 {
 	lbaint_t start, blks;
diff --git a/config.mk b/config.mk
index ddf350e..81c2584 100644
--- a/config.mk
+++ b/config.mk
@@ -210,6 +210,11 @@
 LDFLAGS_FINAL += --gc-sections
 endif
 
+# TODO(sjg@chromium.org): Is this correct on Mac OS?
+ifdef CONFIG_FIT_SIGNATURE
+HOSTLIBS	+= -lssl -lcrypto
+endif
+
 ifneq ($(CONFIG_SYS_TEXT_BASE),)
 CPPFLAGS += -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE)
 endif
@@ -268,6 +273,16 @@
 CFLAGS_STACK := $(call cc-option,-fstack-usage)
 CFLAGS += $(CFLAGS_STACK)
 
+BCURDIR = $(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
+
+ifeq ($(findstring examples/,$(BCURDIR)),)
+ifeq ($(CONFIG_SPL_BUILD),)
+ifdef FTRACE
+CFLAGS += -finstrument-functions -DFTRACE
+endif
+endif
+endif
+
 # $(CPPFLAGS) sets -g, which causes gcc to pass a suitable -g<format>
 # option to the assembler.
 AFLAGS_DEBUG :=
@@ -330,7 +345,6 @@
 #########################################################################
 
 # Allow boards to use custom optimize flags on a per dir/file basis
-BCURDIR = $(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
 ALL_AFLAGS = $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR))
 ALL_CFLAGS = $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR))
 EXTRA_CPPFLAGS = $(CPPFLAGS_$(BCURDIR)/$(@F)) $(CPPFLAGS_$(BCURDIR))
diff --git a/doc/README.plan9 b/doc/README.plan9
new file mode 100644
index 0000000..2d3d0e0
--- /dev/null
+++ b/doc/README.plan9
@@ -0,0 +1,18 @@
+Plan 9 from Bell Labs kernel images require additional setup to pass
+configuration information to the kernel.  An environment variable named
+confaddr must be defined with the same value as CONFADDR (see mem.h).
+Use of this facility is optional, but should be preferable to manual
+configuration.
+
+When booting an image, arguments supplied to the bootm command will be
+copied to CONFADDR.  If no arguments are specified, the contents of the
+bootargs environment variable will be copied.
+
+If no command line arguments or bootargs are defined, CONFADDR is left
+uninitialized to permit manual configuration.  For example, PC-style
+configuration could be simulated by issuing a fatload in bootcmd:
+
+  # setenv bootcmd fatload mmc 0 $confaddr plan9.ini; ...; bootm
+
+Steven Stallion
+June 2013
diff --git a/doc/README.srio-pcie-boot-corenet b/doc/README.srio-pcie-boot-corenet
index cd7e7ee..2b1f76b 100644
--- a/doc/README.srio-pcie-boot-corenet
+++ b/doc/README.srio-pcie-boot-corenet
@@ -21,13 +21,13 @@
 	e) Slave's RCW should configure the SerDes for SRIO or PCIE boot port, set
 	   the boot location to SRIO or PCIE, and holdoff all the cores.
 
-	----------        -----------             -----------
-	|		  |       |         |             |         |
-	|		  |       |         |             |         |
+	-----------       -----------             -----------
+	|         |       |         |             |         |
+	|         |       |         |             |         |
 	| NorFlash|<----->| Master  |SRIO or PCIE |  Slave  |<---->[EEPROM]
-	|		  |       |         |<===========>|         |
-	|		  |       |         |             |         |
-	----------        -----------             -----------
+	|         |       |         |<===========>|         |
+	|         |       |         |             |         |
+	-----------       -----------             -----------
 
 The example based on P4080DS platform:
 	Two P4080DS platforms can be used to implement the boot from SRIO or PCIE.
@@ -87,26 +87,32 @@
 	   Please refer to the examples given above.
 
 	2. U-Boot image's compilation.
-		For master, U-Boot image should be generated normally.
+	   For master, U-Boot image should be generated normally.
 
-		For example, master U-Boot image used on P4080DS should be compiled with
+	   For example, master U-Boot image used on P4080DS should be compiled with
 
 				make P4080DS_config.
 
-		For slave, U-Boot image should be generated specifically by
+	   For slave, U-Boot image should be generated specifically by
 
 				make xxxx_SRIO_PCIE_BOOT_config.
 
-		For example, slave U-Boot image used on P4080DS should be compiled with
+	   For example, slave U-Boot image used on P4080DS should be compiled with
 
 				make P4080DS_SRIO_PCIE_BOOT_config.
 
 	3. Necessary modifications based on a specific environment.
-		For a specific environment, the addresses of the slave's U-Boot image,
-		UCode, ENV stored in master's NorFlash, and any other configurations
-		can be modified in the file:
-					include/configs/corenet_ds.h.
+	   For a specific environment, the addresses of the slave's U-Boot image,
+	   UCode, ENV stored in master's NorFlash, and any other configurations
+	   can be modified in the file:
+				include/configs/corenet_ds.h.
 
 	4. Set and save the environment variable "bootmaster" with "SRIO1", "SRIO2"
 	   or "PCIE1", "PCIE2", "PCIE3" for master, and then restart it in order to
 	   perform the role as a master for boot from SRIO or PCIE.
+
+NOTE: When the Slave's ENV parameters are stored in Master's NorFlash,
+      it can fetch them through PCIE or SRIO interface. But the ENV
+      parameters can not be modified by "saveenv" or other commands under
+      the Slave's u-boot environment, because the Slave can not erase,
+      write Master's NorFlash by PCIE or SRIO link.
diff --git a/doc/README.trace b/doc/README.trace
new file mode 100644
index 0000000..b535c06
--- /dev/null
+++ b/doc/README.trace
@@ -0,0 +1,361 @@
+#
+# Copyright (c) 2013 The Chromium OS Authors.
+#
+# 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 Foundatio; 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
+#
+
+Tracing in U-Boot
+=================
+
+U-Boot supports a simple tracing feature which allows a record of excecution
+to be collected and sent to a host machine for analysis. At present the
+main use for this is to profile boot time.
+
+
+Overview
+--------
+
+The trace feature uses GCC's instrument-functions feature to trace all
+function entry/exit points. These are then recorded in a memory buffer.
+The memory buffer can be saved to the host over a network link using
+tftpput or by writing to an attached memory device such as MMC.
+
+On the host, the file is first converted with a tool called 'proftool',
+which extracts useful information from it. The resulting trace output
+resembles that emitted by Linux's ftrace feature, so can be visually
+displayed by pytimechart.
+
+
+Quick-start using Sandbox
+-------------------------
+
+Sandbox is a build of U-Boot that can run under Linux so it is a convenient
+way of trying out tracing before you use it on your actual board. To do
+this, follow these steps:
+
+Add the following to include/configs/sandbox.h (if not already there)
+
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE		(16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR		0x00100000
+
+Build sandbox U-Boot with tracing enabled:
+
+$ make FTRACE=1 O=sandbox sandbox_config
+$ make FTRACE=1 O=sandbox
+
+Run sandbox, wait for a bit of trace information to appear, and then capture
+a trace:
+
+$ ./sandbox/u-boot
+
+
+U-Boot 2013.04-rc2-00100-ga72fcef (Apr 17 2013 - 19:25:24)
+
+DRAM:  128 MiB
+trace: enabled
+Using default environment
+
+In:    serial
+Out:   serial
+Err:   serial
+=>trace stats
+        671,406 function sites
+         69,712 function calls
+              0 untracked function calls
+         73,373 traced function calls
+             16 maximum observed call depth
+             15 call depth limit
+         66,491 calls not traced due to depth
+=>trace stats
+        671,406 function sites
+      1,279,450 function calls
+              0 untracked function calls
+        950,490 traced function calls (333217 dropped due to overflow)
+             16 maximum observed call depth
+             15 call depth limit
+      1,275,767 calls not traced due to depth
+=>trace calls 0 e00000
+Call list dumped to 00000000, size 0xae0a40
+=>print
+baudrate=115200
+profbase=0
+profoffset=ae0a40
+profsize=e00000
+stderr=serial
+stdin=serial
+stdout=serial
+
+Environment size: 117/8188 bytes
+=>sb save host 0 trace 0 ${profoffset}
+11405888 bytes written in 10 ms (1.1 GiB/s)
+=>reset
+
+
+Then run proftool to convert the trace information to ftrace format.
+
+$ ./sandbox/tools/proftool -m sandbox/System.map -p trace dump-ftrace >trace.txt
+
+Finally run pytimechart to display it:
+
+$ pytimechart trace.txt
+
+Using this tool you can zoom and pan across the trace, with the function
+calls on the left and little marks representing the start and end of each
+function.
+
+
+CONFIG Options
+--------------
+
+- CONFIG_TRACE
+		Enables the trace feature in U-Boot.
+
+- CONFIG_CMD_TRACE
+		Enables the trace command.
+
+- CONFIG_TRACE_BUFFER_SIZE
+		Size of trace buffer to allocate for U-Boot. This buffer is
+		used after relocation, as a place to put function tracing
+		information. The address of the buffer is determined by
+		the relocation code.
+
+- CONFIG_TRACE_EARLY
+		Define this to start tracing early, before relocation.
+
+- CONFIG_TRACE_EARLY_SIZE
+		Size of 'early' trace buffer. Before U-Boot has relocated
+		it doesn't have a proper trace buffer. On many boards
+		you can define an area of memory to use for the trace
+		buffer until the 'real' trace buffer is available after
+		relocation. The contents of this buffer are then copied to
+		the real buffer.
+
+- CONFIG_TRACE_EARLY_ADDR
+		Address of early trace buffer
+
+
+Building U-Boot with Tracing Enabled
+------------------------------------
+
+Pass 'FTRACE=1' to the U-Boot Makefile to actually instrument the code.
+This is kept as a separate option so that it is easy to enable/disable
+instrumenting from the command line instead of having to change board
+config files.
+
+
+Collecting Trace Data
+---------------------
+
+When you run U-Boot on your board it will collect trace data up to the
+limit of the trace buffer size you have specified. Once that is exhausted
+no more data will be collected.
+
+Collecting trace data has an affect on execution time/performance. You
+will notice this particularly with trvial functions - the overhead of
+recording their execution may even exceed their normal execution time.
+In practice this doesn't matter much so long as you are aware of the
+effect. Once you have done your optimisations, turn off tracing before
+doing end-to-end timing.
+
+The best time to start tracing is right at the beginning of U-Boot. The
+best time to stop tracing is right at the end. In practice it is hard
+to achieve these ideals.
+
+This implementation enables tracing early in board_init_f(). This means
+that it captures most of the board init process, missing only the
+early architecture-specific init. However, it also misses the entire
+SPL stage if there is one.
+
+U-Boot typically ends with a 'bootm' command which loads and runs an
+OS. There is useful trace data in the execution of that bootm
+command. Therefore this implementation provides a way to collect trace
+data after bootm has finished processing, but just before it jumps to
+the OS. In practical terms, U-Boot runs the 'fakegocmd' environment
+variable at this point. This variable should have a short script which
+collects the trace data and writes it somewhere.
+
+Trace data collection relies on a microsecond timer, accesed through
+timer_get_us(). So the first think you should do is make sure that
+this produces sensible results for your board. Suitable sources for
+this timer include high resolution timers, PWMs or profile timers if
+available. Most modern SOCs have a suitable timer for this. Make sure
+that you mark this timer (and anything it calls) with
+__attribute__((no_instrument_function)) so that the trace library can
+use it without causing an infinite loop.
+
+
+Commands
+--------
+
+The trace command has variable sub-commands:
+
+- stats
+		Display tracing statistics
+
+- pause
+		Pause tracing
+
+- resume
+		Resume tracing
+
+- funclist [<addr> <size>]
+		Dump a list of functions into the buffer
+
+- calls  [<addr> <size>]
+		Dump function call trace into buffer
+
+If the address and size are not given, these are obtained from environment
+variables (see below). In any case the environment variables are updated
+after the command runs.
+
+
+Environment Variables
+---------------------
+
+The following are used:
+
+- profbase
+		Base address of trace output buffer
+
+- profoffset
+		Offset of first unwritten byte in trace output buffer
+
+- profsize
+		Size of trace output buffer
+
+All of these are set by the 'trace calls' command.
+
+These variables keep track of the amount of data written to the trace
+output buffer by the 'trace' command. The trace commands which write data
+to the output buffer can use these to specify the buffer to write to, and
+update profoffset each time. This allows successive commands to append data
+to the same buffer, for example:
+
+	trace funclist 10000 e00000
+	trace calls
+
+(the latter command appends more data to the buffer).
+
+
+- fakegocmd
+		Specifies commands to run just before booting the OS. This
+		is a useful time to write the trace data to the host for
+		processing.
+
+
+Writing Out Trace Data
+----------------------
+
+Once the trace data is in an output buffer in memory there are various ways
+to transmit it to the host. Notably you can use tftput to send the data
+over a network link:
+
+fakegocmd=trace pause; usb start; set autoload n; bootp;
+	trace calls 10000000 1000000;
+	tftpput ${profbase} ${profoffset} 192.168.1.4:/tftpboot/calls
+
+This starts up USB (to talk to an attached USB Ethernet dongle), writes
+a trace log to address 10000000 and sends it to a host machine using
+TFTP. After this, U-Boot will boot the OS normally, albeit a little
+later.
+
+
+Converting Trace Output Data
+----------------------------
+
+The trace output data is kept in a binary format which is not documented
+here. To convert it into something useful, you can use proftool.
+
+This tool must be given the U-Boot map file and the trace data received
+from running that U-Boot. It produces a text output file.
+
+Options
+	-m <map_file>
+		Specify U-Boot map file
+
+	-p <trace_file>
+		Specifiy profile/trace file
+
+Commands:
+
+- dump-ftrace
+	Write a text dump of the file in Linux ftrace format to stdout
+
+
+Viewing the Trace Data
+----------------------
+
+You can use pytimechart for this (sudo apt-get pytimechart might work on
+your Debian-style machine, and use your favourite search engine to obtain
+documentation). It expects the file to have a .txt extension. The program
+has terse user interface but is very convenient for viewing U-Boot
+profile information.
+
+
+Workflow Suggestions
+--------------------
+
+The following suggestions may be helpful if you are trying to reduce boot
+time:
+
+1. Enable CONFIG_BOOTSTAGE and CONFIG_BOOTSTAGE_REPORT. This should get
+you are helpful overall snapshot of the boot time.
+
+2. Build U-Boot with tracing and run it. Note the difference in boot time
+(it is common for tracing to add 10% to the time)
+
+3. Collect the trace information as descibed above. Use this to find where
+all the time is being spent.
+
+4. Take a look at that code and see if you can optimise it. Perhaps it is
+possible to speed up the initialisation of a device, or remove an unused
+feature.
+
+5. Rebuild, run and collect again. Compare your results.
+
+6. Keep going until you run out of steam, or your boot is fast enough.
+
+
+Configuring Trace
+-----------------
+
+There are a few parameters in the code that you may want to consider.
+There is a function call depth limit (set to 15 by default). When the
+stack depth goes above this then no tracing information is recorded.
+The maximum depth reached is recorded and displayed by the 'trace stats'
+command.
+
+
+Future Work
+-----------
+
+Tracing could be a little tidier in some areas, for example providing
+run-time configuration options for trace.
+
+Some other features that might be useful:
+
+- Trace filter to select which functions are recorded
+- Sample-based profiling using a timer interrupt
+- Better control over trace depth
+- Compression of trace information
+
+
+Simon Glass <sjg@chromium.org>
+April 2013
diff --git a/doc/device-tree-bindings/exynos/dwmmc.txt b/doc/device-tree-bindings/exynos/dwmmc.txt
new file mode 100644
index 0000000..566da3b
--- /dev/null
+++ b/doc/device-tree-bindings/exynos/dwmmc.txt
@@ -0,0 +1,54 @@
+* Exynos 5250 DWC_mobile_storage
+
+The Exynos 5250 provides DWC_mobile_storage interface which supports
+. Embedded Multimedia Cards (EMMC-version 4.5)
+. Secure Digital memory (SD mem-version 2.0)
+. Secure Digital I/O (SDIO-version 3.0)
+. Consumer Electronics Advanced Transport Architecture (CE-ATA-version 1.1)
+
+The Exynos 5250 DWC_mobile_storage provides four channels.
+SOC specific and Board specific properties are channel specific.
+
+Required SoC Specific Properties:
+
+- compatible: should be
+	- samsung,exynos5250-dwmmc: for exynos5250 platforms
+
+- reg: physical base address of the controller and length of memory mapped
+	region.
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- samsung,bus-width: The width of the bus used to interface the devices
+	supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO).
+	. Typically the bus width is 4 or 8.
+- samsung,timing: The timing values to be written into the
+	Drv/sample clock selection register of corresponding channel.
+	. It is comprised of 3 values corresponding to the 3 fileds
+	  'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL register.
+	. SelClk_sample: Select sample clock among 8 shifted clocks.
+	. SelClk_drv: Select drv clock among 8 shifted clocks.
+	. DIVRATIO: Clock Divide ratio select.
+	. The above 3 values are used by the clock phase shifter.
+
+Example:
+
+mmc@12200000 {
+	samsung,bus-width = <8>;
+	samsung,timing = <1 3 3>;
+	samsung,removable = <1>;
+}
+In the above example,
+	. The bus width is 8
+	. Timing is comprised of 3 values as explained below
+		1 - SelClk_sample
+		3 - SelClk_drv
+		3 - DIVRATIO
+	. The 'removable' flag indicates whether the the particilar device
+	  cannot be removed (always present) or it is a removable device.
+		1 - Indicates that the device is removable.
+		0 - Indicates that the device cannot be removed.
diff --git a/doc/device-tree-bindings/input/cros-ec-keyb.txt b/doc/device-tree-bindings/input/cros-ec-keyb.txt
new file mode 100644
index 0000000..3118276
--- /dev/null
+++ b/doc/device-tree-bindings/input/cros-ec-keyb.txt
@@ -0,0 +1,79 @@
+CROS_EC Keyboard
+
+The CROS_EC (Matrix Keyboard Protocol) allows communcation with a secondary
+micro used for keyboard, and possible other features.
+
+The CROS_EC keyboard uses this protocol to receive key scans and produce input
+in U-Boot.
+
+Required properties :
+- compatible : "google,cros-ec-keyb"
+- google,key-rows : Number of key rows
+- google,key-columns : Number of key columns
+
+Optional properties, in addition to those specified by the shared
+matrix-keyboard bindings:
+
+- linux,fn-keymap: a second keymap, same specification as the
+  matrix-keyboard-controller spec but to be used when the KEY_FN modifier
+  key is pressed.
+- google,repeat-delay-ms : delay in milliseconds before repeat starts
+- google,repeat-rate-ms : delay between each subsequent key press
+- google,ghost-filter : enable ghost filtering for this device
+
+Example, taken from daisy:
+
+cros-ec-keyb {
+	compatible = "google,cros-ec-keyb";
+	google,key-rows = <8>;
+	google,key-columns = <13>;
+	google,ghost-filter;
+	google,repeat-delay-ms = <240>;
+	google,repeat-rate-ms = <30>;
+	/*
+		* Keymap entries take the form of 0xRRCCKKKK where
+		* RR=Row CC=Column KKKK=Key Code
+		* The values below are for a US keyboard layout and
+		* are taken from the Linux driver. Note that the
+		* 102ND key is not used for US keyboards.
+		*/
+	linux,keymap = <
+		/* CAPSLCK F1         B          F10     */
+		0x0001003a 0x0002003c 0x00030030 0x00040044
+		/* N       =          R_ALT      ESC     */
+		0x00060031 0x0008000d 0x000a0064 0x01010001
+		/* F4      G          F7         H       */
+		0x0102003e 0x01030022 0x01040041 0x01060023
+		/* '       F9         BKSPACE    L_CTRL  */
+		0x01080028 0x01090043 0x010b000e 0x0200001d
+		/* TAB     F3         T          F6      */
+		0x0201000f 0x0202003d 0x02030014 0x02040040
+		/* ]       Y          102ND      [       */
+		0x0205001b 0x02060015 0x02070056 0x0208001a
+		/* F8      GRAVE      F2         5       */
+		0x02090042 0x03010029 0x0302003c 0x03030006
+		/* F5      6          -          \       */
+		0x0304003f 0x03060007 0x0308000c 0x030b002b
+		/* R_CTRL  A          D          F       */
+		0x04000061 0x0401001e 0x04020020 0x04030021
+		/* S       K          J          ;       */
+		0x0404001f 0x04050025 0x04060024 0x04080027
+		/* L       ENTER      Z          C       */
+		0x04090026 0x040b001c 0x0501002c 0x0502002e
+		/* V       X          ,          M       */
+		0x0503002f 0x0504002d 0x05050033 0x05060032
+		/* L_SHIFT /          .          SPACE   */
+		0x0507002a 0x05080035 0x05090034 0x050B0039
+		/* 1       3          4          2       */
+		0x06010002 0x06020004 0x06030005 0x06040003
+		/* 8       7          0          9       */
+		0x06050009 0x06060008 0x0608000b 0x0609000a
+		/* L_ALT   DOWN       RIGHT      Q       */
+		0x060a0038 0x060b006c 0x060c006a 0x07010010
+		/* E       R          W          I       */
+		0x07020012 0x07030013 0x07040011 0x07050017
+		/* U       R_SHIFT    P          O       */
+		0x07060016 0x07070036 0x07080019 0x07090018
+		/* UP      LEFT    */
+		0x070b0067 0x070c0069>;
+};
diff --git a/doc/device-tree-bindings/misc/cros-ec.txt b/doc/device-tree-bindings/misc/cros-ec.txt
new file mode 100644
index 0000000..07ea7cd
--- /dev/null
+++ b/doc/device-tree-bindings/misc/cros-ec.txt
@@ -0,0 +1,38 @@
+Chrome OS CROS_EC Binding
+======================
+
+The device tree node which describes the operation of the CROS_EC interface
+is as follows:
+
+Required properties :
+- compatible = "google,cros-ec"
+
+Optional properties :
+- spi-max-frequency : Sets the maximum frequency (in Hz) for SPI bus
+   operation
+- i2c-max-frequency : Sets the maximum frequency (in Hz) for I2C bus
+   operation
+- ec-interrupt : Selects the EC interrupt, defined as a GPIO according
+   to the platform
+- optimise-flash-write : Boolean property - if present then flash blocks
+   containing all 0xff will not be written, since we assume that the EC
+   uses that pattern for erased blocks
+
+The CROS_EC node should appear as a subnode of the interrupt that connects it
+to the EC (e.g. i2c, spi, lpc). The reg property (as usual) will indicate
+the unit address on that bus.
+
+
+Example
+=======
+
+	spi@131b0000 {
+		cros-ec@0 {
+			reg = <0>;
+			compatible = "google,cros-ec";
+			spi-max-frequency = <5000000>;
+			ec-interrupt = <&gpio 174 1>;
+			optimise-flash-write;
+			status = "disabled";
+		};
+	};
diff --git a/doc/mkimage.1 b/doc/mkimage.1
index 39652c8..14374da 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -4,7 +4,17 @@
 mkimage \- Generate image for U-Boot
 .SH SYNOPSIS
 .B mkimage
-.RB [\fIoptions\fP]
+.RB "\-l [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " \-f [" "image tree source file" "]" " [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " \-F [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " (legacy mode)"
+
 .SH "DESCRIPTION"
 The
 .B mkimage
@@ -26,7 +36,8 @@
 The new
 .I FIT (Flattened Image Tree) format
 allows for more flexibility in handling images of various types and also
-enhances integrity protection of images with stronger checksums.
+enhances integrity protection of images with stronger checksums. It also
+supports verified boot.
 
 .SH "OPTIONS"
 
@@ -67,6 +78,10 @@
 Set entry point with a hex number.
 
 .TP
+.BI "\-l"
+List the contents of an image.
+
+.TP
 .BI "\-n [" "image name" "]"
 Set image name to 'image name'.
 
@@ -82,6 +97,12 @@
 .B Create FIT image:
 
 .TP
+.BI "\-c [" "comment" "]"
+Specifies a comment to be added when signing. This is typically a useful
+message which describes how the image was signed or some other useful
+information.
+
+.TP
 .BI "\-D [" "dtc options" "]"
 Provide special options to the device tree compiler that is used to
 create the image.
@@ -91,6 +112,33 @@
 Image tree source file that describes the structure and contents of the
 FIT image.
 
+.TP
+.BI "\-F"
+Indicates that an existing FIT image should be modified. No dtc
+compilation is performed and the -f flag should not be given.
+This can be used to sign images with additional keys after initial image
+creation.
+
+.TP
+.BI "\-k [" "key_directory" "]"
+Specifies the directory containing keys to use for signing. This directory
+should contain a private key file <name>.key for use with signing and a
+certificate <name>.crt (containing the public key) for use with verification.
+
+.TP
+.BI "\-K [" "key_destination" "]"
+Specifies a compiled device tree binary file (typically .dtb) to write
+public key information into. When a private key is used to sign an image,
+the corresponding public key is written into this file for for run-time
+verification. Typically the file here is the device tree binary used by
+CONFIG_OF_CONTROL in U-Boot.
+
+.TP
+.BI "\-r
+Specifies that keys used to sign the FIT are required. This means that they
+must be verified for the image to boot. Without this option, the verification
+will be optional (useful for testing but not for release).
+
 .SH EXAMPLES
 
 List image information:
@@ -109,10 +157,29 @@
 .nf
 .B mkimage -f kernel.its kernel.itb
 .fi
+.P
+Create FIT image with compressed kernel and sign it with keys in the
+/public/signing-keys directory. Add corresponding public keys into u-boot.dtb,
+skipping those for which keys cannot be found. Also add a comment.
+.nf
+.B mkimage -f kernel.its -k /public/signing-keys -K u-boot.dtb \\\\
+-c "Kernel 3.8 image for production devices" kernel.itb
+.fi
+
+.P
+Update an existing FIT image, signing it with additional keys.
+Add corresponding public keys into u-boot.dtb. This will resign all images
+with keys that are available in the new directory. Images that request signing
+with unavailable keys are skipped.
+.nf
+.B mkimage -F -k /secret/signing-keys -K u-boot.dtb \\\\
+-c "Kernel 3.8 image for production devices" kernel.itb
+.fi
 
 .SH HOMEPAGE
 http://www.denx.de/wiki/U-Boot/WebHome
 .PP
 .SH AUTHOR
 This manual page was written by Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
-and Wolfgang Denk <wd@denx.de>
+and Wolfgang Denk <wd@denx.de>. It was updated for image signing by
+Simon Glass <sjg@chromium.org>.
diff --git a/doc/uImage.FIT/sign-configs.its b/doc/uImage.FIT/sign-configs.its
new file mode 100644
index 0000000..3c17f04
--- /dev/null
+++ b/doc/uImage.FIT/sign-configs.its
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel@1 {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "lzo";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			hash@1 {
+				algo = "sha1";
+			};
+		};
+		fdt@1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash@1 {
+				algo = "sha1";
+			};
+		};
+	};
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+			signature@1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/doc/uImage.FIT/sign-images.its b/doc/uImage.FIT/sign-images.its
new file mode 100644
index 0000000..f69326a
--- /dev/null
+++ b/doc/uImage.FIT/sign-images.its
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel@1 {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			signature@1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+			};
+		};
+		fdt@1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			signature@1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+			};
+		};
+	};
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+		};
+	};
+};
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
new file mode 100644
index 0000000..bc9f3fa
--- /dev/null
+++ b/doc/uImage.FIT/signature.txt
@@ -0,0 +1,382 @@
+U-Boot FIT Signature Verification
+=================================
+
+Introduction
+------------
+FIT supports hashing of images so that these hashes can be checked on
+loading. This protects against corruption of the image. However it does not
+prevent the substitution of one image for another.
+
+The signature feature allows the hash to be signed with a private key such
+that it can be verified using a public key later. Provided that the private
+key is kept secret and the public key is stored in a non-volatile place,
+any image can be verified in this way.
+
+See verified-boot.txt for more general information on verified boot.
+
+
+Concepts
+--------
+Some familiarity with public key cryptography is assumed in this section.
+
+The procedure for signing is as follows:
+
+   - hash an image in the FIT
+   - sign the hash with a private key to produce a signature
+   - store the resulting signature in the FIT
+
+The procedure for verification is:
+
+   - read the FIT
+   - obtain the public key
+   - extract the signature from the FIT
+   - hash the image from the FIT
+   - verify (with the public key) that the extracted signature matches the
+       hash
+
+The signing is generally performed by mkimage, as part of making a firmware
+image for the device. The verification is normally done in U-Boot on the
+device.
+
+
+Algorithms
+----------
+In principle any suitable algorithm can be used to sign and verify a hash.
+At present only one class of algorithms is supported: SHA1 hashing with RSA.
+This works by hashing the image to produce a 20-byte hash.
+
+While it is acceptable to bring in large cryptographic libraries such as
+openssl on the host side (e.g. mkimage), it is not desirable for U-Boot.
+For the run-time verification side, it is important to keep code and data
+size as small as possible.
+
+For this reason the RSA image verification uses pre-processed public keys
+which can be used with a very small amount of code - just some extraction
+of data from the FDT and exponentiation mod n. Code size impact is a little
+under 5KB on Tegra Seaboard, for example.
+
+It is relatively straightforward to add new algorithms if required. If
+another RSA variant is needed, then it can be added to the table in
+image-sig.c. If another algorithm is needed (such as DSA) then it can be
+placed alongside rsa.c, and its functions added to the table in image-sig.c
+also.
+
+
+Creating an RSA key and certificate
+-----------------------------------
+To create a new public key, size 2048 bits:
+
+$ openssl genrsa -F4 -out keys/dev.key 2048
+
+To create a certificate for this:
+
+$ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt
+
+If you like you can look at the public key also:
+
+$ openssl rsa -in keys/dev.key -pubout
+
+
+Device Tree Bindings
+--------------------
+The following properties are required in the FIT's signature node(s) to
+allow thes signer to operate. These should be added to the .its file.
+Signature nodes sit at the same level as hash nodes and are called
+signature@1, signature@2, etc.
+
+- algo: Algorithm name (e.g. "sha1,rs2048")
+
+- key-name-hint: Name of key to use for signing. The keys will normally be in
+a single directory (parameter -k to mkimage). For a given key <name>, its
+private key is stored in <name>.key and the certificate is stored in
+<name>.crt.
+
+When the image is signed, the following properties are added (mandatory):
+
+- value: The signature data (e.g. 256 bytes for 2048-bit RSA)
+
+When the image is signed, the following properties are optional:
+
+- timestamp: Time when image was signed (standard Unix time_t format)
+
+- signer-name: Name of the signer (e.g. "mkimage")
+
+- signer-version: Version string of the signer (e.g. "2013.01")
+
+- comment: Additional information about the signer or image
+
+For config bindings (see Signed Configurations below), the following
+additional properties are optional:
+
+- sign-images: A list of images to sign, each being a property of the conf
+node that contains then. The default is "kernel,fdt" which means that these
+two images will be looked up in the config and signed if present.
+
+For config bindings, these properties are added by the signer:
+
+- hashed-nodes: A list of nodes which were hashed by the signer. Each is
+	a string - the full path to node. A typical value might be:
+
+	hashed-nodes = "/", "/configurations/conf@1", "/images/kernel@1",
+		"/images/kernel@1/hash@1", "/images/fdt@1",
+		"/images/fdt@1/hash@1";
+
+- hashed-strings: The start and size of the string region of the FIT that
+	was hashed
+
+Example: See sign-images.its for an example image tree source file and
+sign-configs.its for config signing.
+
+
+Public Key Storage
+------------------
+In order to verify an image that has been signed with a public key we need to
+have a trusted public key. This cannot be stored in the signed image, since
+it would be easy to alter. For this implementation we choose to store the
+public key in U-Boot's control FDT (using CONFIG_OF_CONTROL).
+
+Public keys should be stored as sub-nodes in a /signature node. Required
+properties are:
+
+- algo: Algorithm name (e.g. "sha1,rs2048")
+
+Optional properties are:
+
+- key-name-hint: Name of key used for signing. This is only a hint since it
+is possible for the name to be changed. Verification can proceed by checking
+all available signing keys until one matches.
+
+- required: If present this indicates that the key must be verified for the
+image / configuration to be considered valid. Only required keys are
+normally verified by the FIT image booting algorithm. Valid values are
+"image" to force verification of all images, and "conf" to force verfication
+of the selected configuration (which then relies on hashes in the images to
+verify those).
+
+Each signing algorithm has its own additional properties.
+
+For RSA the following are mandatory:
+
+- rsa,num-bits: Number of key bits (e.g. 2048)
+- rsa,modulus: Modulus (N) as a big-endian multi-word integer
+- rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer
+- rsa,n0-inverse: -1 / modulus[0] mod 2^32
+
+
+Signed Configurations
+---------------------
+While signing images is useful, it does not provide complete protection
+against several types of attack. For example, it it possible to create a
+FIT with the same signed images, but with the configuration changed such
+that a different one is selected (mix and match attack). It is also possible
+to substitute a signed image from an older FIT version into a newer FIT
+(roll-back attack).
+
+As an example, consider this FIT:
+
+/ {
+	images {
+		kernel@1 {
+			data = <data for kernel1>
+			signature@1 {
+				algo = "sha1,rsa2048";
+				value = <...kernel signature 1...>
+			};
+		};
+		kernel@2 {
+			data = <data for kernel2>
+			signature@1 {
+				algo = "sha1,rsa2048";
+				value = <...kernel signature 2...>
+			};
+		};
+		fdt@1 {
+			data = <data for fdt1>;
+			signature@1 {
+				algo = "sha1,rsa2048";
+				vaue = <...fdt signature 1...>
+			};
+		};
+		fdt@2 {
+			data = <data for fdt2>;
+			signature@1 {
+				algo = "sha1,rsa2048";
+				vaue = <...fdt signature 2...>
+			};
+		};
+	};
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+		};
+		conf@1 {
+			kernel = "kernel@2";
+			fdt = "fdt@2";
+		};
+	};
+};
+
+Since both kernels are signed it is easy for an attacker to add a new
+configuration 3 with kernel 1 and fdt 2:
+
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+		};
+		conf@1 {
+			kernel = "kernel@2";
+			fdt = "fdt@2";
+		};
+		conf@3 {
+			kernel = "kernel@1";
+			fdt = "fdt@2";
+		};
+	};
+
+With signed images, nothing protects against this. Whether it gains an
+advantage for the attacker is debatable, but it is not secure.
+
+To solved this problem, we support signed configurations. In this case it
+is the configurations that are signed, not the image. Each image has its
+own hash, and we include the hash in the configuration signature.
+
+So the above example is adjusted to look like this:
+
+/ {
+	images {
+		kernel@1 {
+			data = <data for kernel1>
+			hash@1 {
+				algo = "sha1";
+				value = <...kernel hash 1...>
+			};
+		};
+		kernel@2 {
+			data = <data for kernel2>
+			hash@1 {
+				algo = "sha1";
+				value = <...kernel hash 2...>
+			};
+		};
+		fdt@1 {
+			data = <data for fdt1>;
+			hash@1 {
+				algo = "sha1";
+				value = <...fdt hash 1...>
+			};
+		};
+		fdt@2 {
+			data = <data for fdt2>;
+			hash@1 {
+				algo = "sha1";
+				value = <...fdt hash 2...>
+			};
+		};
+	};
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+			signature@1 {
+				algo = "sha1,rsa2048";
+				value = <...conf 1 signature...>;
+			};
+		};
+		conf@2 {
+			kernel = "kernel@2";
+			fdt = "fdt@2";
+			signature@1 {
+				algo = "sha1,rsa2048";
+				value = <...conf 1 signature...>;
+			};
+		};
+	};
+};
+
+
+You can see that we have added hashes for all images (since they are no
+longer signed), and a signature to each configuration. In the above example,
+mkimage will sign configurations/conf@1, the kernel and fdt that are
+pointed to by the configuration (/images/kernel@1, /images/kernel@1/hash@1,
+/images/fdt@1, /images/fdt@1/hash@1) and the root structure of the image
+(so that it isn't possible to add or remove root nodes). The signature is
+written into /configurations/conf@1/signature@1/value. It can easily be
+verified later even if the FIT has been signed with other keys in the
+meantime.
+
+
+Verification
+------------
+FITs are verified when loaded. After the configuration is selected a list
+of required images is produced. If there are 'required' public keys, then
+each image must be verified against those keys. This means that every image
+that might be used by the target needs to be signed with 'required' keys.
+
+This happens automatically as part of a bootm command when FITs are used.
+
+
+Enabling FIT Verification
+-------------------------
+In addition to the options to enable FIT itself, the following CONFIGs must
+be enabled:
+
+CONFIG_FIT_SIGNATURE - enable signing and verfication in FITs
+CONFIG_RSA - enable RSA algorithm for signing
+
+
+Testing
+-------
+An easy way to test signing and verfication is to use the test script
+provided in test/vboot/vboot_test.sh. This uses sandbox (a special version
+of U-Boot which runs under Linux) to show the operation of a 'bootm'
+command loading and verifying images.
+
+A sample run is show below:
+
+$ make O=sandbox sandbox_config
+$ make O=sandbox
+$ O=sandbox ./test/vboot/vboot_test.sh
+Simple Verified Boot Test
+=========================
+
+Please see doc/uImage.FIT/verified-boot.txt for more information
+
+Build keys
+Build FIT with signed images
+Test Verified Boot Run: unsigned signatures:: OK
+Sign images
+Test Verified Boot Run: signed images: OK
+Build FIT with signed configuration
+Test Verified Boot Run: unsigned config: OK
+Sign images
+Test Verified Boot Run: signed config: OK
+
+Test passed
+
+
+Future Work
+-----------
+- Roll-back protection using a TPM is done using the tpm command. This can
+be scripted, but we might consider a default way of doing this, built into
+bootm.
+
+
+Possible Future Work
+--------------------
+- Add support for other RSA/SHA variants, such as rsa4096,sha512.
+- Other algorithms besides RSA
+- More sandbox tests for failure modes
+- Passwords for keys/certificates
+- Perhaps implement OAEP
+- Enhance bootm to permit scripted signature verification (so that a script
+can verify an image but not actually boot it)
+
+
+Simon Glass
+sjg@chromium.org
+1-1-13
diff --git a/doc/uImage.FIT/verified-boot.txt b/doc/uImage.FIT/verified-boot.txt
new file mode 100644
index 0000000..3c83fbc
--- /dev/null
+++ b/doc/uImage.FIT/verified-boot.txt
@@ -0,0 +1,104 @@
+U-Boot Verified Boot
+====================
+
+Introduction
+------------
+Verified boot here means the verification of all software loaded into a
+machine during the boot process to ensure that it is authorised and correct
+for that machine.
+
+Verified boot extends from the moment of system reset to as far as you wish
+into the boot process. An example might be loading U-Boot from read-only
+memory, then loading a signed kernel, then using the kernel's dm-verity
+driver to mount a signed root filesystem.
+
+A key point is that it is possible to field-upgrade the software on machines
+which use verified boot. Since the machine will only run software that has
+been correctly signed, it is safe to read software from an updatable medium.
+It is also possible to add a secondary signed firmware image, in read-write
+memory, so that firmware can easily be upgraded in a secure manner.
+
+
+Signing
+-------
+Verified boot uses cryptographic algorithms to 'sign' software images.
+Images are signed using a private key known only to the signer, but can
+be verified using a public key. As its name suggests the public key can be
+made available without risk to the verification process. The private and
+public keys are mathematically related. For more information on how this
+works look up "public key cryptography" and "RSA" (a particular algorithm).
+
+The signing and verification process looks something like this:
+
+
+      Signing                                      Verification
+      =======                                      ============
+
+ +--------------+                   *
+ | RSA key pair |                   *             +---------------+
+ | .key  .crt   |                   *             | Public key in |
+ +--------------+       +------> public key ----->| trusted place |
+       |                |           *             +---------------+
+       |                |           *                    |
+       v                |           *                    v
+   +---------+          |           *              +--------------+
+   |         |----------+           *              |              |
+   | signer  |                      *              |    U-Boot    |
+   |         |----------+           *              |  signature   |--> yes/no
+   +---------+          |           *              | verification |
+      ^                 |           *              |              |
+      |                 |           *              +--------------+
+      |                 |           *                    ^
+ +----------+           |           *                    |
+ | Software |           +----> signed image -------------+
+ |  image   |                       *
+ +----------+                       *
+
+
+The signature algorithm relies only on the public key to do its work. Using
+this key it checks the signature that it finds in the image. If it verifies
+then we know that the image is OK.
+
+The public key from the signer allows us to verify and therefore trust
+software from updatable memory.
+
+It is critical that the public key be secure and cannot be tampered with.
+It can be stored in read-only memory, or perhaps protected by other on-chip
+crypto provided by some modern SOCs. If the public key can ben changed, then
+the verification is worthless.
+
+
+Chaining Images
+---------------
+The above method works for a signer providing images to a run-time U-Boot.
+It is also possible to extend this scheme to a second level, like this:
+
+1. Master private key is used by the signer to sign a first-stage image.
+2. Master public key is placed in read-only memory.
+2. Secondary private key is created and used to sign second-stage images.
+3. Secondary public key is placed in first stage images
+4. We use the master public key to verify the first-stage image. We then
+use the secondary public key in the first-stage image to verify the second-
+state image.
+5. This chaining process can go on indefinitely. It is recommended to use a
+different key at each stage, so that a compromise in one place will not
+affect the whole change.
+
+
+Flattened Image Tree (FIT)
+--------------------------
+The FIT format is alreay widely used in U-Boot. It is a flattened device
+tree (FDT) in a particular format, with images contained within. FITs
+include hashes to verify images, so it is relatively straightforward to
+add signatures as well.
+
+The public key can be stored in U-Boot's CONFIG_OF_CONTROL device tree in
+a standard place. Then when a FIT it loaded it can be verified using that
+public key. Multiple keys and multiple signatures are supported.
+
+See signature.txt for more information.
+
+
+Simon Glass
+sjg@chromium.org
+1-1-13
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index f3adf64..bb8e644 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -133,8 +133,7 @@
 	/*
 	 * Setup PWM Lookup-Table
 	 */
-	for (i = 0; i < sizeof(pwm_lookup) / sizeof(struct pwm_lookup_entry);
-	     i++) {
+	for (i = 0; i < ARRAY_SIZE(pwm_lookup); i++) {
 		int address = DTT_PWM_LOOKUP_BASE + 2 * i;
 		val = pwm_lookup[i].temp;
 		if (is_lm64(sensor))
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 0805e86..4331190 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -27,6 +27,7 @@
 
 COBJS-$(CONFIG_I8042_KBD) += i8042.o
 COBJS-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o
+COBJS-$(CONFIG_CROS_EC_KEYB) += cros_ec_keyb.o
 ifdef CONFIG_PS2KBD
 COBJS-y += keyboard.o pc_keyb.o
 COBJS-$(CONFIG_PS2MULT) += ps2mult.o ps2ser.o
diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c
new file mode 100644
index 0000000..c197308
--- /dev/null
+++ b/drivers/input/cros_ec_keyb.c
@@ -0,0 +1,261 @@
+/*
+ * Chromium OS Matrix Keyboard
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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 <cros_ec.h>
+#include <fdtdec.h>
+#include <input.h>
+#include <key_matrix.h>
+#include <stdio_dev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+	KBC_MAX_KEYS		= 8,	/* Maximum keys held down at once */
+};
+
+static struct keyb {
+	struct cros_ec_dev *dev;		/* The CROS_EC device */
+	struct input_config input;	/* The input layer */
+	struct key_matrix matrix;	/* The key matrix layer */
+	int key_rows;			/* Number of keyboard rows */
+	int key_cols;			/* Number of keyboard columns */
+	unsigned int repeat_delay_ms;	/* Time before autorepeat starts */
+	unsigned int repeat_rate_ms;	/* Autorepeat rate in ms */
+	int ghost_filter;		/* 1 to enable ghost filter, else 0 */
+	int inited;			/* 1 if keyboard is ready */
+} config;
+
+
+/**
+ * Check the keyboard controller and return a list of key matrix positions
+ * for which a key is pressed
+ *
+ * @param config	Keyboard config
+ * @param keys		List of keys that we have detected
+ * @param max_count	Maximum number of keys to return
+ * @return number of pressed keys, 0 for none
+ */
+static int check_for_keys(struct keyb *config,
+			   struct key_matrix_key *keys, int max_count)
+{
+	struct key_matrix_key *key;
+	struct mbkp_keyscan scan;
+	unsigned int row, col, bit, data;
+	int num_keys;
+
+	if (cros_ec_scan_keyboard(config->dev, &scan)) {
+		debug("%s: keyboard scan failed\n", __func__);
+		return -1;
+	}
+
+	for (col = num_keys = bit = 0; col < config->matrix.num_cols;
+			col++) {
+		for (row = 0; row < config->matrix.num_rows; row++) {
+			unsigned int mask = 1 << (bit & 7);
+
+			data = scan.data[bit / 8];
+			if ((data & mask) && num_keys < max_count) {
+				key = keys + num_keys++;
+				key->row = row;
+				key->col = col;
+				key->valid = 1;
+			}
+			bit++;
+		}
+	}
+
+	return num_keys;
+}
+
+/**
+ * Test if keys are available to be read
+ *
+ * @return 0 if no keys available, 1 if keys are available
+ */
+static int kbd_tstc(void)
+{
+	/* Just get input to do this for us */
+	return config.inited ? input_tstc(&config.input) : 0;
+}
+
+/**
+ * Read a key
+ *
+ * @return ASCII key code, or 0 if no key, or -1 if error
+ */
+static int kbd_getc(void)
+{
+	/* Just get input to do this for us */
+	return config.inited ? input_getc(&config.input) : 0;
+}
+
+/**
+ * Check the keyboard, and send any keys that are pressed.
+ *
+ * This is called by input_tstc() and input_getc() when they need more
+ * characters
+ *
+ * @param input		Input configuration
+ * @return 1, to indicate that we have something to look at
+ */
+int cros_ec_kbc_check(struct input_config *input)
+{
+	static struct key_matrix_key last_keys[KBC_MAX_KEYS];
+	static int last_num_keys;
+	struct key_matrix_key keys[KBC_MAX_KEYS];
+	int keycodes[KBC_MAX_KEYS];
+	int num_keys, num_keycodes;
+	int irq_pending, sent;
+
+	/*
+	 * Loop until the EC has no more keyscan records, or we have
+	 * received at least one character. This means we know that tstc()
+	 * will always return non-zero if keys have been pressed.
+	 *
+	 * Without this loop, a key release (which generates no new ascii
+	 * characters) will cause us to exit this function, and just tstc()
+	 * may return 0 before all keys have been read from the EC.
+	 */
+	do {
+		irq_pending = cros_ec_interrupt_pending(config.dev);
+		if (irq_pending) {
+			num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS);
+			last_num_keys = num_keys;
+			memcpy(last_keys, keys, sizeof(keys));
+		} else {
+			/*
+			 * EC doesn't want to be asked, so use keys from last
+			 * time.
+			 */
+			num_keys = last_num_keys;
+			memcpy(keys, last_keys, sizeof(keys));
+		}
+
+		if (num_keys < 0)
+			return -1;
+		num_keycodes = key_matrix_decode(&config.matrix, keys,
+				num_keys, keycodes, KBC_MAX_KEYS);
+		sent = input_send_keycodes(input, keycodes, num_keycodes);
+	} while (irq_pending && !sent);
+
+	return 1;
+}
+
+/**
+ * Decode MBKP keyboard details from the device tree
+ *
+ * @param blob		Device tree blob
+ * @param node		Node to decode from
+ * @param config	Configuration data read from fdt
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_keyb_decode_fdt(const void *blob, int node,
+				struct keyb *config)
+{
+	/*
+	 * Get keyboard rows and columns - at present we are limited to
+	 * 8 columns by the protocol (one byte per row scan)
+	 */
+	config->key_rows = fdtdec_get_int(blob, node, "google,key-rows", 0);
+	config->key_cols = fdtdec_get_int(blob, node, "google,key-columns", 0);
+	if (!config->key_rows || !config->key_cols ||
+			config->key_rows * config->key_cols / 8
+				> CROS_EC_KEYSCAN_COLS) {
+		debug("%s: Invalid key matrix size %d x %d\n", __func__,
+		      config->key_rows, config->key_cols);
+		return -1;
+	}
+	config->repeat_delay_ms = fdtdec_get_int(blob, node,
+						 "google,repeat-delay-ms", 0);
+	config->repeat_rate_ms = fdtdec_get_int(blob, node,
+						"google,repeat-rate-ms", 0);
+	config->ghost_filter = fdtdec_get_bool(blob, node,
+					       "google,ghost-filter");
+	return 0;
+}
+
+/**
+ * Set up the keyboard. This is called by the stdio device handler.
+ *
+ * We want to do this init when the keyboard is actually used rather than
+ * at start-up, since keyboard input may not currently be selected.
+ *
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_init_keyboard(void)
+{
+	const void *blob = gd->fdt_blob;
+	int node;
+
+	config.dev = board_get_cros_ec_dev();
+	if (!config.dev) {
+		debug("%s: no cros_ec device: cannot init keyboard\n",
+		      __func__);
+		return -1;
+	}
+	node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+	if (node < 0) {
+		debug("%s: Node not found\n", __func__);
+		return -1;
+	}
+	if (cros_ec_keyb_decode_fdt(blob, node, &config))
+		return -1;
+	input_set_delays(&config.input, config.repeat_delay_ms,
+			 config.repeat_rate_ms);
+	if (key_matrix_init(&config.matrix, config.key_rows,
+			config.key_cols, config.ghost_filter)) {
+		debug("%s: cannot init key matrix\n", __func__);
+		return -1;
+	}
+	if (key_matrix_decode_fdt(&config.matrix, gd->fdt_blob, node)) {
+		debug("%s: Could not decode key matrix from fdt\n", __func__);
+		return -1;
+	}
+	config.inited = 1;
+	debug("%s: Matrix keyboard %dx%d ready\n", __func__, config.key_rows,
+	      config.key_cols);
+
+	return 0;
+}
+
+int drv_keyboard_init(void)
+{
+	struct stdio_dev dev;
+
+	if (input_init(&config.input, 0)) {
+		debug("%s: Cannot set up input\n", __func__);
+		return -1;
+	}
+	config.input.read_keys = cros_ec_kbc_check;
+
+	memset(&dev, '\0', sizeof(dev));
+	strcpy(dev.name, "cros-ec-keyb");
+	dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+	dev.getc = kbd_getc;
+	dev.tstc = kbd_tstc;
+	dev.start = cros_ec_init_keyboard;
+
+	/* Register the device. cros_ec_init_keyboard() will be called soon */
+	return input_stdio_register(&dev);
+}
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5d869b4..5fbff8a 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -28,6 +28,10 @@
 COBJS-$(CONFIG_ALI152X) += ali512x.o
 COBJS-$(CONFIG_DS4510)  += ds4510.o
 COBJS-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
+COBJS-$(CONFIG_CROS_EC) += cros_ec.o
+COBJS-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
+COBJS-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
+COBJS-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
 COBJS-$(CONFIG_FSL_IIM) += fsl_iim.o
 COBJS-$(CONFIG_GPIO_LED) += gpio_led.o
 COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
new file mode 100644
index 0000000..6e774d9
--- /dev/null
+++ b/drivers/misc/cros_ec.c
@@ -0,0 +1,1304 @@
+/*
+ * Chromium OS cros_ec driver
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <i2c.h>
+#include <cros_ec.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...)	debug(fmt, #b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+enum {
+	/* Timeout waiting for a flash erase command to complete */
+	CROS_EC_CMD_TIMEOUT_MS	= 5000,
+	/* Timeout waiting for a synchronous hash to be recomputed */
+	CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
+};
+
+static struct cros_ec_dev static_dev, *last_dev;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Note: depends on enum ec_current_image */
+static const char * const ec_current_image_name[] = {"unknown", "RO", "RW"};
+
+void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len)
+{
+#ifdef DEBUG
+	int i;
+
+	printf("%s: ", name);
+	if (cmd != -1)
+		printf("cmd=%#x: ", cmd);
+	for (i = 0; i < len; i++)
+		printf("%02x ", data[i]);
+	printf("\n");
+#endif
+}
+
+/*
+ * Calculate a simple 8-bit checksum of a data block
+ *
+ * @param data	Data block to checksum
+ * @param size	Size of data block in bytes
+ * @return checksum value (0 to 255)
+ */
+int cros_ec_calc_checksum(const uint8_t *data, int size)
+{
+	int csum, i;
+
+	for (i = csum = 0; i < size; i++)
+		csum += data[i];
+	return csum & 0xff;
+}
+
+static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+			const void *dout, int dout_len,
+			uint8_t **dinp, int din_len)
+{
+	int ret;
+
+	switch (dev->interface) {
+#ifdef CONFIG_CROS_EC_SPI
+	case CROS_EC_IF_SPI:
+		ret = cros_ec_spi_command(dev, cmd, cmd_version,
+					(const uint8_t *)dout, dout_len,
+					dinp, din_len);
+		break;
+#endif
+#ifdef CONFIG_CROS_EC_I2C
+	case CROS_EC_IF_I2C:
+		ret = cros_ec_i2c_command(dev, cmd, cmd_version,
+					(const uint8_t *)dout, dout_len,
+					dinp, din_len);
+		break;
+#endif
+#ifdef CONFIG_CROS_EC_LPC
+	case CROS_EC_IF_LPC:
+		ret = cros_ec_lpc_command(dev, cmd, cmd_version,
+					(const uint8_t *)dout, dout_len,
+					dinp, din_len);
+		break;
+#endif
+	case CROS_EC_IF_NONE:
+	default:
+		ret = -1;
+	}
+
+	return ret;
+}
+
+/**
+ * Send a command to the CROS-EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev		CROS-EC device
+ * @param cmd		Command to send (EC_CMD_...)
+ * @param cmd_version	Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Response data (may be NULL If din_len=0).
+ *			If not NULL, it will be updated to point to the data
+ *			and will always be double word aligned (64-bits)
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd,
+		int cmd_version, const void *dout, int dout_len, uint8_t **dinp,
+		int din_len)
+{
+	uint8_t *din;
+	int len;
+
+	if (cmd_version != 0 && !dev->cmd_version_is_supported) {
+		debug("%s: Command version >0 unsupported\n", __func__);
+		return -1;
+	}
+	len = send_command(dev, cmd, cmd_version, dout, dout_len,
+				&din, din_len);
+
+	/* If the command doesn't complete, wait a while */
+	if (len == -EC_RES_IN_PROGRESS) {
+		struct ec_response_get_comms_status *resp;
+		ulong start;
+
+		/* Wait for command to complete */
+		start = get_timer(0);
+		do {
+			int ret;
+
+			mdelay(50);	/* Insert some reasonable delay */
+			ret = send_command(dev, EC_CMD_GET_COMMS_STATUS, 0,
+					NULL, 0,
+					(uint8_t **)&resp, sizeof(*resp));
+			if (ret < 0)
+				return ret;
+
+			if (get_timer(start) > CROS_EC_CMD_TIMEOUT_MS) {
+				debug("%s: Command %#02x timeout\n",
+				      __func__, cmd);
+				return -EC_RES_TIMEOUT;
+			}
+		} while (resp->flags & EC_COMMS_STATUS_PROCESSING);
+
+		/* OK it completed, so read the status response */
+		/* not sure why it was 0 for the last argument */
+		len = send_command(dev, EC_CMD_RESEND_RESPONSE, 0,
+				NULL, 0, &din, din_len);
+	}
+
+	debug("%s: len=%d, dinp=%p, *dinp=%p\n", __func__, len, dinp, *dinp);
+	if (dinp) {
+		/* If we have any data to return, it must be 64bit-aligned */
+		assert(len <= 0 || !((uintptr_t)din & 7));
+		*dinp = din;
+	}
+
+	return len;
+}
+
+/**
+ * Send a command to the CROS-EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev		CROS-EC device
+ * @param cmd		Command to send (EC_CMD_...)
+ * @param cmd_version	Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param din           Response data (may be NULL If din_len=0).
+ *			It not NULL, it is a place for ec_command() to copy the
+ *      data to.
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		      const void *dout, int dout_len,
+		      void *din, int din_len)
+{
+	uint8_t *in_buffer;
+	int len;
+
+	assert((din_len == 0) || din);
+	len = ec_command_inptr(dev, cmd, cmd_version, dout, dout_len,
+			&in_buffer, din_len);
+	if (len > 0) {
+		/*
+		 * If we were asked to put it somewhere, do so, otherwise just
+		 * disregard the result.
+		 */
+		if (din && in_buffer) {
+			assert(len <= din_len);
+			memmove(din, in_buffer, len);
+		}
+	}
+	return len;
+}
+
+int cros_ec_scan_keyboard(struct cros_ec_dev *dev, struct mbkp_keyscan *scan)
+{
+	if (ec_command(dev, EC_CMD_CROS_EC_STATE, 0, NULL, 0, scan,
+		       sizeof(scan->data)) < sizeof(scan->data))
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen)
+{
+	struct ec_response_get_version *r;
+
+	if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
+			(uint8_t **)&r, sizeof(*r)) < sizeof(*r))
+		return -1;
+
+	if (maxlen > sizeof(r->version_string_ro))
+		maxlen = sizeof(r->version_string_ro);
+
+	switch (r->current_image) {
+	case EC_IMAGE_RO:
+		memcpy(id, r->version_string_ro, maxlen);
+		break;
+	case EC_IMAGE_RW:
+		memcpy(id, r->version_string_rw, maxlen);
+		break;
+	default:
+		return -1;
+	}
+
+	id[maxlen - 1] = '\0';
+	return 0;
+}
+
+int cros_ec_read_version(struct cros_ec_dev *dev,
+		       struct ec_response_get_version **versionp)
+{
+	if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
+			(uint8_t **)versionp, sizeof(**versionp))
+			< sizeof(**versionp))
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp)
+{
+	if (ec_command_inptr(dev, EC_CMD_GET_BUILD_INFO, 0, NULL, 0,
+			(uint8_t **)strp, EC_HOST_PARAM_SIZE) < 0)
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_read_current_image(struct cros_ec_dev *dev,
+		enum ec_current_image *image)
+{
+	struct ec_response_get_version *r;
+
+	if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
+			(uint8_t **)&r, sizeof(*r)) < sizeof(*r))
+		return -1;
+
+	*image = r->current_image;
+	return 0;
+}
+
+static int cros_ec_wait_on_hash_done(struct cros_ec_dev *dev,
+				  struct ec_response_vboot_hash *hash)
+{
+	struct ec_params_vboot_hash p;
+	ulong start;
+
+	start = get_timer(0);
+	while (hash->status == EC_VBOOT_HASH_STATUS_BUSY) {
+		mdelay(50);	/* Insert some reasonable delay */
+
+		p.cmd = EC_VBOOT_HASH_GET;
+		if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+		       hash, sizeof(*hash)) < 0)
+			return -1;
+
+		if (get_timer(start) > CROS_EC_CMD_HASH_TIMEOUT_MS) {
+			debug("%s: EC_VBOOT_HASH_GET timeout\n", __func__);
+			return -EC_RES_TIMEOUT;
+		}
+	}
+	return 0;
+}
+
+
+int cros_ec_read_hash(struct cros_ec_dev *dev,
+		struct ec_response_vboot_hash *hash)
+{
+	struct ec_params_vboot_hash p;
+	int rv;
+
+	p.cmd = EC_VBOOT_HASH_GET;
+	if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+		       hash, sizeof(*hash)) < 0)
+		return -1;
+
+	/* If the EC is busy calculating the hash, fidget until it's done. */
+	rv = cros_ec_wait_on_hash_done(dev, hash);
+	if (rv)
+		return rv;
+
+	/* If the hash is valid, we're done. Otherwise, we have to kick it off
+	 * again and wait for it to complete. Note that we explicitly assume
+	 * that hashing zero bytes is always wrong, even though that would
+	 * produce a valid hash value. */
+	if (hash->status == EC_VBOOT_HASH_STATUS_DONE && hash->size)
+		return 0;
+
+	debug("%s: No valid hash (status=%d size=%d). Compute one...\n",
+	      __func__, hash->status, hash->size);
+
+	p.cmd = EC_VBOOT_HASH_RECALC;
+	p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
+	p.nonce_size = 0;
+	p.offset = EC_VBOOT_HASH_OFFSET_RW;
+
+	if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+		       hash, sizeof(*hash)) < 0)
+		return -1;
+
+	rv = cros_ec_wait_on_hash_done(dev, hash);
+	if (rv)
+		return rv;
+
+	debug("%s: hash done\n", __func__);
+
+	return 0;
+}
+
+static int cros_ec_invalidate_hash(struct cros_ec_dev *dev)
+{
+	struct ec_params_vboot_hash p;
+	struct ec_response_vboot_hash *hash;
+
+	/* We don't have an explict command for the EC to discard its current
+	 * hash value, so we'll just tell it to calculate one that we know is
+	 * wrong (we claim that hashing zero bytes is always invalid).
+	 */
+	p.cmd = EC_VBOOT_HASH_RECALC;
+	p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
+	p.nonce_size = 0;
+	p.offset = 0;
+	p.size = 0;
+
+	debug("%s:\n", __func__);
+
+	if (ec_command_inptr(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+		       (uint8_t **)&hash, sizeof(*hash)) < 0)
+		return -1;
+
+	/* No need to wait for it to finish */
+	return 0;
+}
+
+int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd,
+		uint8_t flags)
+{
+	struct ec_params_reboot_ec p;
+
+	p.cmd = cmd;
+	p.flags = flags;
+
+	if (ec_command_inptr(dev, EC_CMD_REBOOT_EC, 0, &p, sizeof(p), NULL, 0)
+			< 0)
+		return -1;
+
+	if (!(flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) {
+		/*
+		 * EC reboot will take place immediately so delay to allow it
+		 * to complete.  Note that some reboot types (EC_REBOOT_COLD)
+		 * will reboot the AP as well, in which case we won't actually
+		 * get to this point.
+		 */
+		/*
+		 * TODO(rspangler@chromium.org): Would be nice if we had a
+		 * better way to determine when the reboot is complete.  Could
+		 * we poll a memory-mapped LPC value?
+		 */
+		udelay(50000);
+	}
+
+	return 0;
+}
+
+int cros_ec_interrupt_pending(struct cros_ec_dev *dev)
+{
+	/* no interrupt support : always poll */
+	if (!fdt_gpio_isvalid(&dev->ec_int))
+		return 1;
+
+	return !gpio_get_value(dev->ec_int.gpio);
+}
+
+int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_cros_ec_info *info)
+{
+	if (ec_command(dev, EC_CMD_CROS_EC_INFO, 0, NULL, 0, info,
+			sizeof(*info)) < sizeof(*info))
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr)
+{
+	struct ec_response_host_event_mask *resp;
+
+	/*
+	 * Use the B copy of the event flags, because the main copy is already
+	 * used by ACPI/SMI.
+	 */
+	if (ec_command_inptr(dev, EC_CMD_HOST_EVENT_GET_B, 0, NULL, 0,
+		       (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp))
+		return -1;
+
+	if (resp->mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INVALID))
+		return -1;
+
+	*events_ptr = resp->mask;
+	return 0;
+}
+
+int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events)
+{
+	struct ec_params_host_event_mask params;
+
+	params.mask = events;
+
+	/*
+	 * Use the B copy of the event flags, so it affects the data returned
+	 * by cros_ec_get_host_events().
+	 */
+	if (ec_command_inptr(dev, EC_CMD_HOST_EVENT_CLEAR_B, 0,
+		       &params, sizeof(params), NULL, 0) < 0)
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_flash_protect(struct cros_ec_dev *dev,
+		       uint32_t set_mask, uint32_t set_flags,
+		       struct ec_response_flash_protect *resp)
+{
+	struct ec_params_flash_protect params;
+
+	params.mask = set_mask;
+	params.flags = set_flags;
+
+	if (ec_command(dev, EC_CMD_FLASH_PROTECT, EC_VER_FLASH_PROTECT,
+		       &params, sizeof(params),
+		       resp, sizeof(*resp)) < sizeof(*resp))
+		return -1;
+
+	return 0;
+}
+
+static int cros_ec_check_version(struct cros_ec_dev *dev)
+{
+	struct ec_params_hello req;
+	struct ec_response_hello *resp;
+
+#ifdef CONFIG_CROS_EC_LPC
+	/* LPC has its own way of doing this */
+	if (dev->interface == CROS_EC_IF_LPC)
+		return cros_ec_lpc_check_version(dev);
+#endif
+
+	/*
+	 * TODO(sjg@chromium.org).
+	 * There is a strange oddity here with the EC. We could just ignore
+	 * the response, i.e. pass the last two parameters as NULL and 0.
+	 * In this case we won't read back very many bytes from the EC.
+	 * On the I2C bus the EC gets upset about this and will try to send
+	 * the bytes anyway. This means that we will have to wait for that
+	 * to complete before continuing with a new EC command.
+	 *
+	 * This problem is probably unique to the I2C bus.
+	 *
+	 * So for now, just read all the data anyway.
+	 */
+	dev->cmd_version_is_supported = 1;
+	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
+		       (uint8_t **)&resp, sizeof(*resp)) > 0) {
+		/* It appears to understand new version commands */
+		dev->cmd_version_is_supported = 1;
+	} else {
+		dev->cmd_version_is_supported = 0;
+		if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req,
+			      sizeof(req), (uint8_t **)&resp,
+			      sizeof(*resp)) < 0) {
+			debug("%s: Failed both old and new command style\n",
+				__func__);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int cros_ec_test(struct cros_ec_dev *dev)
+{
+	struct ec_params_hello req;
+	struct ec_response_hello *resp;
+
+	req.in_data = 0x12345678;
+	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
+		       (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp)) {
+		printf("ec_command_inptr() returned error\n");
+		return -1;
+	}
+	if (resp->out_data != req.in_data + 0x01020304) {
+		printf("Received invalid handshake %x\n", resp->out_data);
+		return -1;
+	}
+
+	return 0;
+}
+
+int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region,
+		      uint32_t *offset, uint32_t *size)
+{
+	struct ec_params_flash_region_info p;
+	struct ec_response_flash_region_info *r;
+	int ret;
+
+	p.region = region;
+	ret = ec_command_inptr(dev, EC_CMD_FLASH_REGION_INFO,
+			 EC_VER_FLASH_REGION_INFO,
+			 &p, sizeof(p), (uint8_t **)&r, sizeof(*r));
+	if (ret != sizeof(*r))
+		return -1;
+
+	if (offset)
+		*offset = r->offset;
+	if (size)
+		*size = r->size;
+
+	return 0;
+}
+
+int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, uint32_t size)
+{
+	struct ec_params_flash_erase p;
+
+	p.offset = offset;
+	p.size = size;
+	return ec_command_inptr(dev, EC_CMD_FLASH_ERASE, 0, &p, sizeof(p),
+			NULL, 0);
+}
+
+/**
+ * Write a single block to the flash
+ *
+ * Write a block of data to the EC flash. The size must not exceed the flash
+ * write block size which you can obtain from cros_ec_flash_write_burst_size().
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to write for a particular region.
+ *
+ * Attempting to write to the region where the EC is currently running from
+ * will result in an error.
+ *
+ * @param dev		CROS-EC device
+ * @param data		Pointer to data buffer to write
+ * @param offset	Offset within flash to write to.
+ * @param size		Number of bytes to write
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_flash_write_block(struct cros_ec_dev *dev,
+		const uint8_t *data, uint32_t offset, uint32_t size)
+{
+	struct ec_params_flash_write p;
+
+	p.offset = offset;
+	p.size = size;
+	assert(data && p.size <= sizeof(p.data));
+	memcpy(p.data, data, p.size);
+
+	return ec_command_inptr(dev, EC_CMD_FLASH_WRITE, 0,
+			  &p, sizeof(p), NULL, 0) >= 0 ? 0 : -1;
+}
+
+/**
+ * Return optimal flash write burst size
+ */
+static int cros_ec_flash_write_burst_size(struct cros_ec_dev *dev)
+{
+	struct ec_params_flash_write p;
+	return sizeof(p.data);
+}
+
+/**
+ * Check if a block of data is erased (all 0xff)
+ *
+ * This function is useful when dealing with flash, for checking whether a
+ * data block is erased and thus does not need to be programmed.
+ *
+ * @param data		Pointer to data to check (must be word-aligned)
+ * @param size		Number of bytes to check (must be word-aligned)
+ * @return 0 if erased, non-zero if any word is not erased
+ */
+static int cros_ec_data_is_erased(const uint32_t *data, int size)
+{
+	assert(!(size & 3));
+	size /= sizeof(uint32_t);
+	for (; size > 0; size -= 4, data++)
+		if (*data != -1U)
+			return 0;
+
+	return 1;
+}
+
+int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
+		     uint32_t offset, uint32_t size)
+{
+	uint32_t burst = cros_ec_flash_write_burst_size(dev);
+	uint32_t end, off;
+	int ret;
+
+	/*
+	 * TODO: round up to the nearest multiple of write size.  Can get away
+	 * without that on link right now because its write size is 4 bytes.
+	 */
+	end = offset + size;
+	for (off = offset; off < end; off += burst, data += burst) {
+		uint32_t todo;
+
+		/* If the data is empty, there is no point in programming it */
+		todo = min(end - off, burst);
+		if (dev->optimise_flash_write &&
+				cros_ec_data_is_erased((uint32_t *)data, todo))
+			continue;
+
+		ret = cros_ec_flash_write_block(dev, data, off, todo);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * Read a single block from the flash
+ *
+ * Read a block of data from the EC flash. The size must not exceed the flash
+ * write block size which you can obtain from cros_ec_flash_write_burst_size().
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to read for a particular region.
+ *
+ * @param dev		CROS-EC device
+ * @param data		Pointer to data buffer to read into
+ * @param offset	Offset within flash to read from
+ * @param size		Number of bytes to read
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_flash_read_block(struct cros_ec_dev *dev, uint8_t *data,
+				 uint32_t offset, uint32_t size)
+{
+	struct ec_params_flash_read p;
+
+	p.offset = offset;
+	p.size = size;
+
+	return ec_command(dev, EC_CMD_FLASH_READ, 0,
+			  &p, sizeof(p), data, size) >= 0 ? 0 : -1;
+}
+
+int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
+		    uint32_t size)
+{
+	uint32_t burst = cros_ec_flash_write_burst_size(dev);
+	uint32_t end, off;
+	int ret;
+
+	end = offset + size;
+	for (off = offset; off < end; off += burst, data += burst) {
+		ret = cros_ec_flash_read_block(dev, data, off,
+					    min(end - off, burst));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
+			 const uint8_t *image, int image_size)
+{
+	uint32_t rw_offset, rw_size;
+	int ret;
+
+	if (cros_ec_flash_offset(dev, EC_FLASH_REGION_RW, &rw_offset, &rw_size))
+		return -1;
+	if (image_size > rw_size)
+		return -1;
+
+	/* Invalidate the existing hash, just in case the AP reboots
+	 * unexpectedly during the update. If that happened, the EC RW firmware
+	 * would be invalid, but the EC would still have the original hash.
+	 */
+	ret = cros_ec_invalidate_hash(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Erase the entire RW section, so that the EC doesn't see any garbage
+	 * past the new image if it's smaller than the current image.
+	 *
+	 * TODO: could optimize this to erase just the current image, since
+	 * presumably everything past that is 0xff's.  But would still need to
+	 * round up to the nearest multiple of erase size.
+	 */
+	ret = cros_ec_flash_erase(dev, rw_offset, rw_size);
+	if (ret)
+		return ret;
+
+	/* Write the image */
+	ret = cros_ec_flash_write(dev, image, rw_offset, image_size);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block)
+{
+	struct ec_params_vbnvcontext p;
+	int len;
+
+	p.op = EC_VBNV_CONTEXT_OP_READ;
+
+	len = ec_command(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
+			&p, sizeof(p), block, EC_VBNV_BLOCK_SIZE);
+	if (len < EC_VBNV_BLOCK_SIZE)
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block)
+{
+	struct ec_params_vbnvcontext p;
+	int len;
+
+	p.op = EC_VBNV_CONTEXT_OP_WRITE;
+	memcpy(p.block, block, sizeof(p.block));
+
+	len = ec_command_inptr(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
+			&p, sizeof(p), NULL, 0);
+	if (len < 0)
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state)
+{
+	struct ec_params_ldo_set params;
+
+	params.index = index;
+	params.state = state;
+
+	if (ec_command_inptr(dev, EC_CMD_LDO_SET, 0,
+		       &params, sizeof(params),
+		       NULL, 0))
+		return -1;
+
+	return 0;
+}
+
+int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state)
+{
+	struct ec_params_ldo_get params;
+	struct ec_response_ldo_get *resp;
+
+	params.index = index;
+
+	if (ec_command_inptr(dev, EC_CMD_LDO_GET, 0,
+		       &params, sizeof(params),
+		       (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp))
+		return -1;
+
+	*state = resp->state;
+
+	return 0;
+}
+
+/**
+ * Decode MBKP details from the device tree and allocate a suitable device.
+ *
+ * @param blob		Device tree blob
+ * @param node		Node to decode from
+ * @param devp		Returns a pointer to the new allocated device
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_decode_fdt(const void *blob, int node,
+		struct cros_ec_dev **devp)
+{
+	enum fdt_compat_id compat;
+	struct cros_ec_dev *dev;
+	int parent;
+
+	/* See what type of parent we are inside (this is expensive) */
+	parent = fdt_parent_offset(blob, node);
+	if (parent < 0) {
+		debug("%s: Cannot find node parent\n", __func__);
+		return -1;
+	}
+
+	dev = &static_dev;
+	dev->node = node;
+	dev->parent_node = parent;
+
+	compat = fdtdec_lookup(blob, parent);
+	switch (compat) {
+#ifdef CONFIG_CROS_EC_SPI
+	case COMPAT_SAMSUNG_EXYNOS_SPI:
+		dev->interface = CROS_EC_IF_SPI;
+		if (cros_ec_spi_decode_fdt(dev, blob))
+			return -1;
+		break;
+#endif
+#ifdef CONFIG_CROS_EC_I2C
+	case COMPAT_SAMSUNG_S3C2440_I2C:
+		dev->interface = CROS_EC_IF_I2C;
+		if (cros_ec_i2c_decode_fdt(dev, blob))
+			return -1;
+		break;
+#endif
+#ifdef CONFIG_CROS_EC_LPC
+	case COMPAT_INTEL_LPC:
+		dev->interface = CROS_EC_IF_LPC;
+		break;
+#endif
+	default:
+		debug("%s: Unknown compat id %d\n", __func__, compat);
+		return -1;
+	}
+
+	fdtdec_decode_gpio(blob, node, "ec-interrupt", &dev->ec_int);
+	dev->optimise_flash_write = fdtdec_get_bool(blob, node,
+						    "optimise-flash-write");
+	*devp = dev;
+
+	return 0;
+}
+
+int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
+{
+	char id[MSG_BYTES];
+	struct cros_ec_dev *dev;
+	int node = 0;
+
+	*cros_ecp = NULL;
+	do {
+		node = fdtdec_next_compatible(blob, node,
+					      COMPAT_GOOGLE_CROS_EC);
+		if (node < 0) {
+			debug("%s: Node not found\n", __func__);
+			return 0;
+		}
+	} while (!fdtdec_get_is_enabled(blob, node));
+
+	if (cros_ec_decode_fdt(blob, node, &dev)) {
+		debug("%s: Failed to decode device.\n", __func__);
+		return -CROS_EC_ERR_FDT_DECODE;
+	}
+
+	switch (dev->interface) {
+#ifdef CONFIG_CROS_EC_SPI
+	case CROS_EC_IF_SPI:
+		if (cros_ec_spi_init(dev, blob)) {
+			debug("%s: Could not setup SPI interface\n", __func__);
+			return -CROS_EC_ERR_DEV_INIT;
+		}
+		break;
+#endif
+#ifdef CONFIG_CROS_EC_I2C
+	case CROS_EC_IF_I2C:
+		if (cros_ec_i2c_init(dev, blob))
+			return -CROS_EC_ERR_DEV_INIT;
+		break;
+#endif
+#ifdef CONFIG_CROS_EC_LPC
+	case CROS_EC_IF_LPC:
+		if (cros_ec_lpc_init(dev, blob))
+			return -CROS_EC_ERR_DEV_INIT;
+		break;
+#endif
+	case CROS_EC_IF_NONE:
+	default:
+		return 0;
+	}
+
+	/* we will poll the EC interrupt line */
+	fdtdec_setup_gpio(&dev->ec_int);
+	if (fdt_gpio_isvalid(&dev->ec_int))
+		gpio_direction_input(dev->ec_int.gpio);
+
+	if (cros_ec_check_version(dev)) {
+		debug("%s: Could not detect CROS-EC version\n", __func__);
+		return -CROS_EC_ERR_CHECK_VERSION;
+	}
+
+	if (cros_ec_read_id(dev, id, sizeof(id))) {
+		debug("%s: Could not read KBC ID\n", __func__);
+		return -CROS_EC_ERR_READ_ID;
+	}
+
+	/* Remember this device for use by the cros_ec command */
+	last_dev = *cros_ecp = dev;
+	debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
+
+	return 0;
+}
+
+#ifdef CONFIG_CMD_CROS_EC
+int cros_ec_decode_region(int argc, char * const argv[])
+{
+	if (argc > 0) {
+		if (0 == strcmp(*argv, "rw"))
+			return EC_FLASH_REGION_RW;
+		else if (0 == strcmp(*argv, "ro"))
+			return EC_FLASH_REGION_RO;
+
+		debug("%s: Invalid region '%s'\n", __func__, *argv);
+	} else {
+		debug("%s: Missing region parameter\n", __func__);
+	}
+
+	return -1;
+}
+
+/**
+ * Perform a flash read or write command
+ *
+ * @param dev		CROS-EC device to read/write
+ * @param is_write	1 do to a write, 0 to do a read
+ * @param argc		Number of arguments
+ * @param argv		Arguments (2 is region, 3 is address)
+ * @return 0 for ok, 1 for a usage error or -ve for ec command error
+ *	(negative EC_RES_...)
+ */
+static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc,
+			 char * const argv[])
+{
+	uint32_t offset, size = -1U, region_size;
+	unsigned long addr;
+	char *endp;
+	int region;
+	int ret;
+
+	region = cros_ec_decode_region(argc - 2, argv + 2);
+	if (region == -1)
+		return 1;
+	if (argc < 4)
+		return 1;
+	addr = simple_strtoul(argv[3], &endp, 16);
+	if (*argv[3] == 0 || *endp != 0)
+		return 1;
+	if (argc > 4) {
+		size = simple_strtoul(argv[4], &endp, 16);
+		if (*argv[4] == 0 || *endp != 0)
+			return 1;
+	}
+
+	ret = cros_ec_flash_offset(dev, region, &offset, &region_size);
+	if (ret) {
+		debug("%s: Could not read region info\n", __func__);
+		return ret;
+	}
+	if (size == -1U)
+		size = region_size;
+
+	ret = is_write ?
+		cros_ec_flash_write(dev, (uint8_t *)addr, offset, size) :
+		cros_ec_flash_read(dev, (uint8_t *)addr, offset, size);
+	if (ret) {
+		debug("%s: Could not %s region\n", __func__,
+		      is_write ? "write" : "read");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct cros_ec_dev *dev = last_dev;
+	const char *cmd;
+	int ret = 0;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	cmd = argv[1];
+	if (0 == strcmp("init", cmd)) {
+		ret = cros_ec_init(gd->fdt_blob, &dev);
+		if (ret) {
+			printf("Could not init cros_ec device (err %d)\n", ret);
+			return 1;
+		}
+		return 0;
+	}
+
+	/* Just use the last allocated device; there should be only one */
+	if (!last_dev) {
+		printf("No CROS-EC device available\n");
+		return 1;
+	}
+	if (0 == strcmp("id", cmd)) {
+		char id[MSG_BYTES];
+
+		if (cros_ec_read_id(dev, id, sizeof(id))) {
+			debug("%s: Could not read KBC ID\n", __func__);
+			return 1;
+		}
+		printf("%s\n", id);
+	} else if (0 == strcmp("info", cmd)) {
+		struct ec_response_cros_ec_info info;
+
+		if (cros_ec_info(dev, &info)) {
+			debug("%s: Could not read KBC info\n", __func__);
+			return 1;
+		}
+		printf("rows     = %u\n", info.rows);
+		printf("cols     = %u\n", info.cols);
+		printf("switches = %#x\n", info.switches);
+	} else if (0 == strcmp("curimage", cmd)) {
+		enum ec_current_image image;
+
+		if (cros_ec_read_current_image(dev, &image)) {
+			debug("%s: Could not read KBC image\n", __func__);
+			return 1;
+		}
+		printf("%d\n", image);
+	} else if (0 == strcmp("hash", cmd)) {
+		struct ec_response_vboot_hash hash;
+		int i;
+
+		if (cros_ec_read_hash(dev, &hash)) {
+			debug("%s: Could not read KBC hash\n", __func__);
+			return 1;
+		}
+
+		if (hash.hash_type == EC_VBOOT_HASH_TYPE_SHA256)
+			printf("type:    SHA-256\n");
+		else
+			printf("type:    %d\n", hash.hash_type);
+
+		printf("offset:  0x%08x\n", hash.offset);
+		printf("size:    0x%08x\n", hash.size);
+
+		printf("digest:  ");
+		for (i = 0; i < hash.digest_size; i++)
+			printf("%02x", hash.hash_digest[i]);
+		printf("\n");
+	} else if (0 == strcmp("reboot", cmd)) {
+		int region;
+		enum ec_reboot_cmd cmd;
+
+		if (argc >= 3 && !strcmp(argv[2], "cold"))
+			cmd = EC_REBOOT_COLD;
+		else {
+			region = cros_ec_decode_region(argc - 2, argv + 2);
+			if (region == EC_FLASH_REGION_RO)
+				cmd = EC_REBOOT_JUMP_RO;
+			else if (region == EC_FLASH_REGION_RW)
+				cmd = EC_REBOOT_JUMP_RW;
+			else
+				return CMD_RET_USAGE;
+		}
+
+		if (cros_ec_reboot(dev, cmd, 0)) {
+			debug("%s: Could not reboot KBC\n", __func__);
+			return 1;
+		}
+	} else if (0 == strcmp("events", cmd)) {
+		uint32_t events;
+
+		if (cros_ec_get_host_events(dev, &events)) {
+			debug("%s: Could not read host events\n", __func__);
+			return 1;
+		}
+		printf("0x%08x\n", events);
+	} else if (0 == strcmp("clrevents", cmd)) {
+		uint32_t events = 0x7fffffff;
+
+		if (argc >= 3)
+			events = simple_strtol(argv[2], NULL, 0);
+
+		if (cros_ec_clear_host_events(dev, events)) {
+			debug("%s: Could not clear host events\n", __func__);
+			return 1;
+		}
+	} else if (0 == strcmp("read", cmd)) {
+		ret = do_read_write(dev, 0, argc, argv);
+		if (ret > 0)
+			return CMD_RET_USAGE;
+	} else if (0 == strcmp("write", cmd)) {
+		ret = do_read_write(dev, 1, argc, argv);
+		if (ret > 0)
+			return CMD_RET_USAGE;
+	} else if (0 == strcmp("erase", cmd)) {
+		int region = cros_ec_decode_region(argc - 2, argv + 2);
+		uint32_t offset, size;
+
+		if (region == -1)
+			return CMD_RET_USAGE;
+		if (cros_ec_flash_offset(dev, region, &offset, &size)) {
+			debug("%s: Could not read region info\n", __func__);
+			ret = -1;
+		} else {
+			ret = cros_ec_flash_erase(dev, offset, size);
+			if (ret) {
+				debug("%s: Could not erase region\n",
+				      __func__);
+			}
+		}
+	} else if (0 == strcmp("regioninfo", cmd)) {
+		int region = cros_ec_decode_region(argc - 2, argv + 2);
+		uint32_t offset, size;
+
+		if (region == -1)
+			return CMD_RET_USAGE;
+		ret = cros_ec_flash_offset(dev, region, &offset, &size);
+		if (ret) {
+			debug("%s: Could not read region info\n", __func__);
+		} else {
+			printf("Region: %s\n", region == EC_FLASH_REGION_RO ?
+					"RO" : "RW");
+			printf("Offset: %x\n", offset);
+			printf("Size:   %x\n", size);
+		}
+	} else if (0 == strcmp("vbnvcontext", cmd)) {
+		uint8_t block[EC_VBNV_BLOCK_SIZE];
+		char buf[3];
+		int i, len;
+		unsigned long result;
+
+		if (argc <= 2) {
+			ret = cros_ec_read_vbnvcontext(dev, block);
+			if (!ret) {
+				printf("vbnv_block: ");
+				for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
+					printf("%02x", block[i]);
+				putc('\n');
+			}
+		} else {
+			/*
+			 * TODO(clchiou): Move this to a utility function as
+			 * cmd_spi might want to call it.
+			 */
+			memset(block, 0, EC_VBNV_BLOCK_SIZE);
+			len = strlen(argv[2]);
+			buf[2] = '\0';
+			for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++) {
+				if (i * 2 >= len)
+					break;
+				buf[0] = argv[2][i * 2];
+				if (i * 2 + 1 >= len)
+					buf[1] = '0';
+				else
+					buf[1] = argv[2][i * 2 + 1];
+				strict_strtoul(buf, 16, &result);
+				block[i] = result;
+			}
+			ret = cros_ec_write_vbnvcontext(dev, block);
+		}
+		if (ret) {
+			debug("%s: Could not %s VbNvContext\n", __func__,
+					argc <= 2 ?  "read" : "write");
+		}
+	} else if (0 == strcmp("test", cmd)) {
+		int result = cros_ec_test(dev);
+
+		if (result)
+			printf("Test failed with error %d\n", result);
+		else
+			puts("Test passed\n");
+	} else if (0 == strcmp("version", cmd)) {
+		struct ec_response_get_version *p;
+		char *build_string;
+
+		ret = cros_ec_read_version(dev, &p);
+		if (!ret) {
+			/* Print versions */
+			printf("RO version:    %1.*s\n",
+			       sizeof(p->version_string_ro),
+			       p->version_string_ro);
+			printf("RW version:    %1.*s\n",
+			       sizeof(p->version_string_rw),
+			       p->version_string_rw);
+			printf("Firmware copy: %s\n",
+				(p->current_image <
+					ARRAY_SIZE(ec_current_image_name) ?
+				ec_current_image_name[p->current_image] :
+				"?"));
+			ret = cros_ec_read_build_info(dev, &build_string);
+			if (!ret)
+				printf("Build info:    %s\n", build_string);
+		}
+	} else if (0 == strcmp("ldo", cmd)) {
+		uint8_t index, state;
+		char *endp;
+
+		if (argc < 3)
+			return CMD_RET_USAGE;
+		index = simple_strtoul(argv[2], &endp, 10);
+		if (*argv[2] == 0 || *endp != 0)
+			return CMD_RET_USAGE;
+		if (argc > 3) {
+			state = simple_strtoul(argv[3], &endp, 10);
+			if (*argv[3] == 0 || *endp != 0)
+				return CMD_RET_USAGE;
+			ret = cros_ec_set_ldo(dev, index, state);
+		} else {
+			ret = cros_ec_get_ldo(dev, index, &state);
+			if (!ret) {
+				printf("LDO%d: %s\n", index,
+					state == EC_LDO_STATE_ON ?
+					"on" : "off");
+			}
+		}
+
+		if (ret) {
+			debug("%s: Could not access LDO%d\n", __func__, index);
+			return ret;
+		}
+	} else {
+		return CMD_RET_USAGE;
+	}
+
+	if (ret < 0) {
+		printf("Error: CROS-EC command failed (error %d)\n", ret);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+U_BOOT_CMD(
+	crosec,	5,	1,	do_cros_ec,
+	"CROS-EC utility command",
+	"init                Re-init CROS-EC (done on startup automatically)\n"
+	"crosec id                  Read CROS-EC ID\n"
+	"crosec info                Read CROS-EC info\n"
+	"crosec curimage            Read CROS-EC current image\n"
+	"crosec hash                Read CROS-EC hash\n"
+	"crosec reboot [rw | ro | cold]  Reboot CROS-EC\n"
+	"crosec events              Read CROS-EC host events\n"
+	"crosec clrevents [mask]    Clear CROS-EC host events\n"
+	"crosec regioninfo <ro|rw>  Read image info\n"
+	"crosec erase <ro|rw>       Erase EC image\n"
+	"crosec read <ro|rw> <addr> [<size>]   Read EC image\n"
+	"crosec write <ro|rw> <addr> [<size>]  Write EC image\n"
+	"crosec vbnvcontext [hexstring]        Read [write] VbNvContext from EC\n"
+	"crosec ldo <idx> [<state>] Switch/Read LDO state\n"
+	"crosec test                run tests on cros_ec\n"
+	"crosec version             Read CROS-EC version"
+);
+#endif
diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c
new file mode 100644
index 0000000..b0060ac
--- /dev/null
+++ b/drivers/misc/cros_ec_i2c.c
@@ -0,0 +1,199 @@
+/*
+ * Chromium OS cros_ec driver - I2C interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <cros_ec.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...)	debug(fmt, #b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len)
+{
+	int old_bus = 0;
+	/* version8, cmd8, arglen8, out8[dout_len], csum8 */
+	int out_bytes = dout_len + 4;
+	/* response8, arglen8, in8[din_len], checksum8 */
+	int in_bytes = din_len + 3;
+	uint8_t *ptr;
+	/* Receive input data, so that args will be dword aligned */
+	uint8_t *in_ptr;
+	int ret;
+
+	old_bus = i2c_get_bus_num();
+
+	/*
+	 * Sanity-check I/O sizes given transaction overhead in internal
+	 * buffers.
+	 */
+	if (out_bytes > sizeof(dev->dout)) {
+		debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+		return -1;
+	}
+	if (in_bytes > sizeof(dev->din)) {
+		debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+		return -1;
+	}
+	assert(dout_len >= 0);
+	assert(dinp);
+
+	/*
+	 * Copy command and data into output buffer so we can do a single I2C
+	 * burst transaction.
+	 */
+	ptr = dev->dout;
+
+	/*
+	 * in_ptr starts of pointing to a dword-aligned input data buffer.
+	 * We decrement it back by the number of header bytes we expect to
+	 * receive, so that the first parameter of the resulting input data
+	 * will be dword aligned.
+	 */
+	in_ptr = dev->din + sizeof(int64_t);
+	if (!dev->cmd_version_is_supported) {
+		/* Send an old-style command */
+		*ptr++ = cmd;
+		out_bytes = dout_len + 1;
+		in_bytes = din_len + 2;
+		in_ptr--;	/* Expect just a status byte */
+	} else {
+		*ptr++ = EC_CMD_VERSION0 + cmd_version;
+		*ptr++ = cmd;
+		*ptr++ = dout_len;
+		in_ptr -= 2;	/* Expect status, length bytes */
+	}
+	memcpy(ptr, dout, dout_len);
+	ptr += dout_len;
+
+	if (dev->cmd_version_is_supported)
+		*ptr++ = (uint8_t)
+			 cros_ec_calc_checksum(dev->dout, dout_len + 3);
+
+	/* Set to the proper i2c bus */
+	if (i2c_set_bus_num(dev->bus_num)) {
+		debug("%s: Cannot change to I2C bus %d\n", __func__,
+			dev->bus_num);
+		return -1;
+	}
+
+	/* Send output data */
+	cros_ec_dump_data("out", -1, dev->dout, out_bytes);
+	ret = i2c_write(dev->addr, 0, 0, dev->dout, out_bytes);
+	if (ret) {
+		debug("%s: Cannot complete I2C write to 0x%x\n",
+			__func__, dev->addr);
+		ret = -1;
+	}
+
+	if (!ret) {
+		ret = i2c_read(dev->addr, 0, 0, in_ptr, in_bytes);
+		if (ret) {
+			debug("%s: Cannot complete I2C read from 0x%x\n",
+				__func__, dev->addr);
+			ret = -1;
+		}
+	}
+
+	/* Return to original bus number */
+	i2c_set_bus_num(old_bus);
+	if (ret)
+		return ret;
+
+	if (*in_ptr != EC_RES_SUCCESS) {
+		debug("%s: Received bad result code %d\n", __func__, *in_ptr);
+		return -(int)*in_ptr;
+	}
+
+	if (dev->cmd_version_is_supported) {
+		int len, csum;
+
+		len = in_ptr[1];
+		if (len + 3 > sizeof(dev->din)) {
+			debug("%s: Received length %#02x too large\n",
+			      __func__, len);
+			return -1;
+		}
+		csum = cros_ec_calc_checksum(in_ptr, 2 + len);
+		if (csum != in_ptr[2 + len]) {
+			debug("%s: Invalid checksum rx %#02x, calced %#02x\n",
+			      __func__, in_ptr[2 + din_len], csum);
+			return -1;
+		}
+		din_len = min(din_len, len);
+		cros_ec_dump_data("in", -1, in_ptr, din_len + 3);
+	} else {
+		cros_ec_dump_data("in (old)", -1, in_ptr, in_bytes);
+	}
+
+	/* Return pointer to dword-aligned input data, if any */
+	*dinp = dev->din + sizeof(int64_t);
+
+	return din_len;
+}
+
+int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+{
+	/* Decode interface-specific FDT params */
+	dev->max_frequency = fdtdec_get_int(blob, dev->node,
+					    "i2c-max-frequency", 100000);
+	dev->bus_num = i2c_get_bus_num_fdt(dev->parent_node);
+	if (dev->bus_num == -1) {
+		debug("%s: Failed to read bus number\n", __func__);
+		return -1;
+	}
+	dev->addr = fdtdec_get_int(blob, dev->node, "reg", -1);
+	if (dev->addr == -1) {
+		debug("%s: Failed to read device address\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Initialize I2C protocol.
+ *
+ * @param dev		CROS_EC device
+ * @param blob		Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob)
+{
+	i2c_init(dev->max_frequency, dev->addr);
+
+	dev->cmd_version_is_supported = 0;
+
+	return 0;
+}
diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c
new file mode 100644
index 0000000..cf0435b
--- /dev/null
+++ b/drivers/misc/cros_ec_lpc.c
@@ -0,0 +1,283 @@
+/*
+ * Chromium OS cros_ec driver - LPC interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cros_ec.h>
+#include <asm/io.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...)	debug(fmt, ##b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+static int wait_for_sync(struct cros_ec_dev *dev)
+{
+	unsigned long start;
+
+	start = get_timer(0);
+	while (inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK) {
+		if (get_timer(start) > 1000) {
+			debug("%s: Timeout waiting for CROS_EC sync\n",
+			      __func__);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Send a command to a LPC CROS_EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev		CROS_EC device
+ * @param cmd		Command to send (EC_CMD_...)
+ * @param cmd_version	Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Place to put pointer to response data
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+static int old_lpc_command(struct cros_ec_dev *dev, uint8_t cmd,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len)
+{
+	int ret, i;
+
+	if (dout_len > EC_OLD_PARAM_SIZE) {
+		debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+		return -1;
+	}
+
+	if (din_len > EC_OLD_PARAM_SIZE) {
+		debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+		return -1;
+	}
+
+	if (wait_for_sync(dev)) {
+		debug("%s: Timeout waiting ready\n", __func__);
+		return -1;
+	}
+
+	debug_trace("cmd: %02x, ", cmd);
+	for (i = 0; i < dout_len; i++) {
+		debug_trace("%02x ", dout[i]);
+		outb(dout[i], EC_LPC_ADDR_OLD_PARAM + i);
+	}
+	outb(cmd, EC_LPC_ADDR_HOST_CMD);
+	debug_trace("\n");
+
+	if (wait_for_sync(dev)) {
+		debug("%s: Timeout waiting ready\n", __func__);
+		return -1;
+	}
+
+	ret = inb(EC_LPC_ADDR_HOST_DATA);
+	if (ret) {
+		debug("%s: CROS_EC result code %d\n", __func__, ret);
+		return -ret;
+	}
+
+	debug_trace("resp: %02x, ", ret);
+	for (i = 0; i < din_len; i++) {
+		dev->din[i] = inb(EC_LPC_ADDR_OLD_PARAM + i);
+		debug_trace("%02x ", dev->din[i]);
+	}
+	debug_trace("\n");
+	*dinp = dev->din;
+
+	return din_len;
+}
+
+int cros_ec_lpc_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len)
+{
+	const int cmd_addr = EC_LPC_ADDR_HOST_CMD;
+	const int data_addr = EC_LPC_ADDR_HOST_DATA;
+	const int args_addr = EC_LPC_ADDR_HOST_ARGS;
+	const int param_addr = EC_LPC_ADDR_HOST_PARAM;
+
+	struct ec_lpc_host_args args;
+	uint8_t *d;
+	int csum;
+	int i;
+
+	/* Fall back to old-style command interface if args aren't supported */
+	if (!dev->cmd_version_is_supported)
+		return old_lpc_command(dev, cmd, dout, dout_len, dinp,
+				       din_len);
+
+	if (dout_len > EC_HOST_PARAM_SIZE) {
+		debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+		return -1;
+	}
+
+	/* Fill in args */
+	args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
+	args.command_version = cmd_version;
+	args.data_size = dout_len;
+
+	/* Calculate checksum */
+	csum = cmd + args.flags + args.command_version + args.data_size;
+	for (i = 0, d = (uint8_t *)dout; i < dout_len; i++, d++)
+		csum += *d;
+
+	args.checksum = (uint8_t)csum;
+
+	if (wait_for_sync(dev)) {
+		debug("%s: Timeout waiting ready\n", __func__);
+		return -1;
+	}
+
+	/* Write args */
+	for (i = 0, d = (uint8_t *)&args; i < sizeof(args); i++, d++)
+		outb(*d, args_addr + i);
+
+	/* Write data, if any */
+	debug_trace("cmd: %02x, ver: %02x", cmd, cmd_version);
+	for (i = 0, d = (uint8_t *)dout; i < dout_len; i++, d++) {
+		outb(*d, param_addr + i);
+		debug_trace("%02x ", *d);
+	}
+
+	outb(cmd, cmd_addr);
+	debug_trace("\n");
+
+	if (wait_for_sync(dev)) {
+		debug("%s: Timeout waiting for response\n", __func__);
+		return -1;
+	}
+
+	/* Check result */
+	i = inb(data_addr);
+	if (i) {
+		debug("%s: CROS_EC result code %d\n", __func__, i);
+		return -i;
+	}
+
+	/* Read back args */
+	for (i = 0, d = (uint8_t *)&args; i < sizeof(args); i++, d++)
+		*d = inb(args_addr + i);
+
+	/*
+	 * If EC didn't modify args flags, then somehow we sent a new-style
+	 * command to an old EC, which means it would have read its params
+	 * from the wrong place.
+	 */
+	if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) {
+		debug("%s: CROS_EC protocol mismatch\n", __func__);
+		return -EC_RES_INVALID_RESPONSE;
+	}
+
+	if (args.data_size > din_len) {
+		debug("%s: CROS_EC returned too much data %d > %d\n",
+		      __func__, args.data_size, din_len);
+		return -EC_RES_INVALID_RESPONSE;
+	}
+
+	/* Read data, if any */
+	for (i = 0, d = (uint8_t *)dev->din; i < args.data_size; i++, d++) {
+		*d = inb(param_addr + i);
+		debug_trace("%02x ", *d);
+	}
+	debug_trace("\n");
+
+	/* Verify checksum */
+	csum = cmd + args.flags + args.command_version + args.data_size;
+	for (i = 0, d = (uint8_t *)dev->din; i < args.data_size; i++, d++)
+		csum += *d;
+
+	if (args.checksum != (uint8_t)csum) {
+		debug("%s: CROS_EC response has invalid checksum\n", __func__);
+		return -EC_RES_INVALID_CHECKSUM;
+	}
+	*dinp = dev->din;
+
+	/* Return actual amount of data received */
+	return args.data_size;
+}
+
+/**
+ * Initialize LPC protocol.
+ *
+ * @param dev		CROS_EC device
+ * @param blob		Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob)
+{
+	int byte, i;
+
+	/* See if we can find an EC at the other end */
+	byte = 0xff;
+	byte &= inb(EC_LPC_ADDR_HOST_CMD);
+	byte &= inb(EC_LPC_ADDR_HOST_DATA);
+	for (i = 0; i < EC_HOST_PARAM_SIZE && (byte == 0xff); i++)
+		byte &= inb(EC_LPC_ADDR_HOST_PARAM + i);
+	if (byte == 0xff) {
+		debug("%s: CROS_EC device not found on LPC bus\n",
+			__func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Test if LPC command args are supported.
+ *
+ * The cheapest way to do this is by looking for the memory-mapped
+ * flag.  This is faster than sending a new-style 'hello' command and
+ * seeing whether the EC sets the EC_HOST_ARGS_FLAG_FROM_HOST flag
+ * in args when it responds.
+ */
+int cros_ec_lpc_check_version(struct cros_ec_dev *dev)
+{
+	if (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) == 'E' &&
+			inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1)
+				== 'C' &&
+			(inb(EC_LPC_ADDR_MEMMAP +
+				EC_MEMMAP_HOST_CMD_FLAGS) &
+				EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED)) {
+		dev->cmd_version_is_supported = 1;
+	} else {
+		/* We are going to use the old IO ports */
+		dev->cmd_version_is_supported = 0;
+	}
+	debug("lpc: version %s\n", dev->cmd_version_is_supported ?
+			"new" : "old");
+
+	return 0;
+}
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
new file mode 100644
index 0000000..e15c833
--- /dev/null
+++ b/drivers/misc/cros_ec_spi.c
@@ -0,0 +1,161 @@
+/*
+ * Chromium OS cros_ec driver - SPI interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <spi.h>
+
+/**
+ * Send a command to a LPC CROS_EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev		CROS_EC device
+ * @param cmd		Command to send (EC_CMD_...)
+ * @param cmd_version	Version of command to send (EC_VER_...)
+ * @param dout		Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp		Returns pointer to response data. This will be
+ *			untouched unless we return a value > 0.
+ * @param din_len	Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len)
+{
+	int in_bytes = din_len + 4;	/* status, length, checksum, trailer */
+	uint8_t *out;
+	uint8_t *p;
+	int csum, len;
+	int rv;
+
+	/*
+	 * Sanity-check input size to make sure it plus transaction overhead
+	 * fits in the internal device buffer.
+	 */
+	if (in_bytes > sizeof(dev->din)) {
+		debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+		return -1;
+	}
+
+	/* We represent message length as a byte */
+	if (dout_len > 0xff) {
+		debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+		return -1;
+	}
+
+	/*
+	 * Clear input buffer so we don't get false hits for MSG_HEADER
+	 */
+	memset(dev->din, '\0', in_bytes);
+
+	if (spi_claim_bus(dev->spi)) {
+		debug("%s: Cannot claim SPI bus\n", __func__);
+		return -1;
+	}
+
+	out = dev->dout;
+	out[0] = cmd_version;
+	out[1] = cmd;
+	out[2] = (uint8_t)dout_len;
+	memcpy(out + 3, dout, dout_len);
+	csum = cros_ec_calc_checksum(out, 3)
+	       + cros_ec_calc_checksum(dout, dout_len);
+	out[3 + dout_len] = (uint8_t)csum;
+
+	/*
+	 * Send output data and receive input data starting such that the
+	 * message body will be dword aligned.
+	 */
+	p = dev->din + sizeof(int64_t) - 2;
+	len = dout_len + 4;
+	cros_ec_dump_data("out", cmd, out, len);
+	rv = spi_xfer(dev->spi, max(len, in_bytes) * 8, out, p,
+		      SPI_XFER_BEGIN | SPI_XFER_END);
+
+	spi_release_bus(dev->spi);
+
+	if (rv) {
+		debug("%s: Cannot complete SPI transfer\n", __func__);
+		return -1;
+	}
+
+	len = min(p[1], din_len);
+	cros_ec_dump_data("in", -1, p, len + 3);
+
+	/* Response code is first byte of message */
+	if (p[0] != EC_RES_SUCCESS) {
+		printf("%s: Returned status %d\n", __func__, p[0]);
+		return -(int)(p[0]);
+	}
+
+	/* Check checksum */
+	csum = cros_ec_calc_checksum(p, len + 2);
+	if (csum != p[len + 2]) {
+		debug("%s: Invalid checksum rx %#02x, calced %#02x\n", __func__,
+		      p[2 + len], csum);
+		return -1;
+	}
+
+	/* Anything else is the response data */
+	*dinp = p + 2;
+
+	return len;
+}
+
+int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+{
+	/* Decode interface-specific FDT params */
+	dev->max_frequency = fdtdec_get_int(blob, dev->node,
+					    "spi-max-frequency", 500000);
+	dev->cs = fdtdec_get_int(blob, dev->node, "reg", 0);
+
+	return 0;
+}
+
+/**
+ * Initialize SPI protocol.
+ *
+ * @param dev		CROS_EC device
+ * @param blob		Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
+{
+	dev->spi = spi_setup_slave_fdt(blob, dev->parent_node,
+				       dev->cs, dev->max_frequency, 0);
+	if (!dev->spi) {
+		debug("%s: Could not setup SPI slave\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 4070d4e..5da20ed 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -129,13 +129,13 @@
 	unsigned int timeout = 100000;
 	u32 retry = 10000;
 	u32 mask, ctrl;
+	ulong start = get_timer(0);
 
 	while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
-		if (timeout == 0) {
+		if (get_timer(start) > timeout) {
 			printf("Timeout on data busy\n");
 			return TIMEOUT;
 		}
-		timeout--;
 	}
 
 	dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
@@ -143,7 +143,6 @@
 	if (data)
 		dwmci_prepare_data(host, data);
 
-
 	dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
 	if (data)
@@ -231,9 +230,8 @@
 	int timeout = 10000;
 	unsigned long sclk;
 
-	if (freq == host->clock)
+	if ((freq == host->clock) || (freq == 0))
 		return 0;
-
 	/*
 	 * If host->mmc_clk didn't define,
 	 * then assume that host->bus_hz is source clock value.
@@ -314,7 +312,7 @@
 static int dwmci_init(struct mmc *mmc)
 {
 	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
-	u32 fifo_size, fifoth_val;
+	u32 fifo_size;
 
 	dwmci_writel(host, DWMCI_PWREN, 1);
 
@@ -323,6 +321,9 @@
 		return -1;
 	}
 
+	/* Enumerate at 400KHz */
+	dwmci_setup_bus(host, mmc->f_min);
+
 	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
 	dwmci_writel(host, DWMCI_INTMASK, 0);
 
@@ -331,13 +332,13 @@
 	dwmci_writel(host, DWMCI_IDINTEN, 0);
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
-	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
-	if (host->fifoth_val)
-		fifoth_val = host->fifoth_val;
-	else
-		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
-			TX_WMARK(fifo_size/2);
-	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
+	if (!host->fifoth_val) {
+		fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+		fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+		host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+			TX_WMARK(fifo_size / 2);
+	}
+	dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
 
 	dwmci_writel(host, DWMCI_CLKENA, 0);
 	dwmci_writel(host, DWMCI_CLKSRC, 0);
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 72a31b7..4238dd9 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#define	DWMMC_MAX_CH_NUM		4
+#define	DWMMC_MAX_FREQ			52000000
+#define	DWMMC_MIN_FREQ			400000
+#define	DWMMC_MMC0_CLKSEL_VAL		0x03030001
+#define	DWMMC_MMC2_CLKSEL_VAL		0x03020001
 
+/*
+ * Function used as callback function to initialise the
+ * CLKSEL register for every mmc channel.
+ */
 static void exynos_dwmci_clksel(struct dwmci_host *host)
 {
-	u32 val;
-	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
-		DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(0);
-
-	dwmci_writel(host, DWMCI_CLKSEL, val);
+	dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
 }
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+unsigned int exynos_dwmci_get_clk(int dev_index)
+{
+	return get_mmc_clk(dev_index);
+}
+
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -	mmc channel number.
+ * regbase -	register base address of mmc channel specified in 'index'.
+ * bus_width -	operating bus width of mmc channel specified in 'index'.
+ * clksel -	value to be written into CLKSEL register in case of FDT.
+ *		NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
 {
 	struct dwmci_host *host = NULL;
+	unsigned int div;
+	unsigned long freq, sclk;
 	host = malloc(sizeof(struct dwmci_host));
 	if (!host) {
 		printf("dwmci_host malloc fail!\n");
 		return 1;
 	}
+	/* request mmc clock vlaue of 52MHz.  */
+	freq = 52000000;
+	sclk = get_mmc_clk(index);
+	div = DIV_ROUND_UP(sclk, freq);
+	/* set the clock divisor for mmc */
+	set_mmc_clk(index, div);
 
-	host->name = EXYNOS_NAME;
+	host->name = "EXYNOS DWMMC";
 	host->ioaddr = (void *)regbase;
 	host->buswidth = bus_width;
+
+	if (clksel) {
+		host->clksel_val = clksel;
+	} else {
+		if (0 == index)
+			host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+		if (2 == index)
+			host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+	}
+
 	host->clksel = exynos_dwmci_clksel;
 	host->dev_index = index;
-
-	add_dwmci(host, 52000000, 400000);
-
+	host->mmc_clk = exynos_dwmci_get_clk;
+	/* Add the mmc channel to be registered with mmc core */
+	if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+		debug("dwmmc%d registration failed\n", index);
+		return -1;
+	}
 	return 0;
 }
 
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+	int index, bus_width;
+	int node_list[DWMMC_MAX_CH_NUM];
+	int err = 0, dev_id, flag, count, i;
+	u32 clksel_val, base, timing[3];
+
+	count = fdtdec_find_aliases_for_id(blob, "mmc",
+				COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list,
+				DWMMC_MAX_CH_NUM);
+
+	for (i = 0; i < count; i++) {
+		int node = node_list[i];
+
+		if (node <= 0)
+			continue;
+
+		/* Extract device id for each mmc channel */
+		dev_id = pinmux_decode_periph_id(blob, node);
+
+		/* Get the bus width from the device node */
+		bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
+		if (bus_width <= 0) {
+			debug("DWMMC: Can't get bus-width\n");
+			return -1;
+		}
+		if (8 == bus_width)
+			flag = PINMUX_FLAG_8BIT_MODE;
+		else
+			flag = PINMUX_FLAG_NONE;
+
+		/* config pinmux for each mmc channel */
+		err = exynos_pinmux_config(dev_id, flag);
+		if (err) {
+			debug("DWMMC not configured\n");
+			return err;
+		}
+
+		index = dev_id - PERIPH_ID_SDMMC0;
+
+		/* Get the base address from the device node */
+		base = fdtdec_get_addr(blob, node, "reg");
+		if (!base) {
+			debug("DWMMC: Can't get base address\n");
+			return -1;
+		}
+		/* Extract the timing info from the node */
+		err = fdtdec_get_int_array(blob, node, "samsung,timing",
+					timing, 3);
+		if (err) {
+			debug("Can't get sdr-timings for divider\n");
+			return -1;
+		}
+
+		clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+				DWMCI_SET_DRV_CLK(timing[1]) |
+				DWMCI_SET_DIV_RATIO(timing[2]));
+		/* Initialise each mmc channel */
+		err = exynos_dwmci_add_port(index, base, bus_width, clksel_val);
+		if (err)
+			debug("dwmmc Channel-%d init failed\n", index);
+	}
+	return 0;
+}
+#endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index e6a296a..73f7195 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -254,7 +254,7 @@
 }
 
 static unsigned long
-mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
+mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
 {
 	int err = 0;
 	struct mmc *mmc = find_mmc_device(dev_num);
@@ -266,7 +266,8 @@
 
 	if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
 		printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-			"The erase range would be change to 0x%lx~0x%lx\n\n",
+		       "The erase range would be change to "
+		       "0x" LBAF "~0x" LBAF "\n\n",
 		       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
 		       ((start + blkcnt + mmc->erase_grp_size)
 		       & ~(mmc->erase_grp_size - 1)) - 1);
@@ -289,14 +290,14 @@
 }
 
 static ulong
-mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
+mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
 	struct mmc_cmd cmd;
 	struct mmc_data data;
 	int timeout = 1000;
 
 	if ((start + blkcnt) > mmc->block_dev.lba) {
-		printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+		printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
 			start + blkcnt, mmc->block_dev.lba);
 		return 0;
 	}
@@ -346,7 +347,7 @@
 }
 
 static ulong
-mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
+mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
 	lbaint_t cur, blocks_todo = blkcnt;
 
@@ -369,7 +370,7 @@
 	return blkcnt;
 }
 
-static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
+static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
 			   lbaint_t blkcnt)
 {
 	struct mmc_cmd cmd;
@@ -408,7 +409,7 @@
 	return blkcnt;
 }
 
-static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
+static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
 {
 	lbaint_t cur, blocks_todo = blkcnt;
 
@@ -420,7 +421,7 @@
 		return 0;
 
 	if ((start + blkcnt) > mmc->block_dev.lba) {
-		printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+		printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
 			start + blkcnt, mmc->block_dev.lba);
 		return 0;
 	}
@@ -1503,3 +1504,137 @@
 	do_preinit();
 	return 0;
 }
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+				unsigned long rpmbsize)
+{
+	int err;
+	struct mmc_cmd cmd;
+
+	/* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = MMC_CMD62_ARG1;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+		return err;
+	}
+
+	/* Boot partition changing mode */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = MMC_CMD62_ARG2;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+		return err;
+	}
+	/* boot partition size is multiple of 128KB */
+	bootsize = (bootsize * 1024) / 128;
+
+	/* Arg: boot partition size */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = bootsize;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+		return err;
+	}
+	/* RPMB partition size is multiple of 128KB */
+	rpmbsize = (rpmbsize * 1024) / 128;
+	/* Arg: RPMB partition size */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = rpmbsize;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+		return err;
+	}
+	return 0;
+}
+
+/*
+ * This function shall form and send the commands to open / close the
+ * boot partition specified by user.
+ *
+ * Input Parameters:
+ * ack: 0x0 - No boot acknowledge sent (default)
+ *	0x1 - Boot acknowledge sent during boot operation
+ * part_num: User selects boot data that will be sent to master
+ *	0x0 - Device not boot enabled (default)
+ *	0x1 - Boot partition 1 enabled for boot
+ *	0x2 - Boot partition 2 enabled for boot
+ * access: User selects partitions to access
+ *	0x0 : No access to boot partition (default)
+ *	0x1 : R/W boot partition 1
+ *	0x2 : R/W boot partition 2
+ *	0x3 : R/W Replay Protected Memory Block (RPMB)
+ *
+ * Returns 0 on success.
+ */
+int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+	int err;
+	struct mmc_cmd cmd;
+
+	/* Boot ack enable, boot partition enable , boot partition access */
+	cmd.cmdidx = MMC_CMD_SWITCH;
+	cmd.resp_type = MMC_RSP_R1b;
+
+	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+			(EXT_CSD_PART_CONF << 16) |
+			((EXT_CSD_BOOT_ACK(ack) |
+			EXT_CSD_BOOT_PART_NUM(part_num) |
+			EXT_CSD_PARTITION_ACCESS(access)) << 8);
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		if (access) {
+			debug("mmc boot partition#%d open fail:Error1 = %d\n",
+			      part_num, err);
+		} else {
+			debug("mmc boot partition#%d close fail:Error = %d\n",
+			      part_num, err);
+		}
+		return err;
+	}
+
+	if (access) {
+		/* 4bit transfer mode at booting time. */
+		cmd.cmdidx = MMC_CMD_SWITCH;
+		cmd.resp_type = MMC_RSP_R1b;
+
+		cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+				(EXT_CSD_BOOT_BUS_WIDTH << 16) |
+				((1 << 0) << 8);
+
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+		if (err) {
+			debug("mmc boot partition#%d open fail:Error2 = %d\n",
+			      part_num, err);
+			return err;
+		}
+	}
+	return 0;
+}
+#endif
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 25f8752..25a5710 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -1797,7 +1797,7 @@
 			};
 			int i;
 
-			for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
+			for (i = 0; i < ARRAY_SIZE(modes); i++) {
 				info->vendor = modes[i];
 				info->start[0] =
 					(ulong)map_physmem(base,
@@ -1883,8 +1883,7 @@
 	/* Issue FLASH reset command */
 	flash_cmd_reset(info);
 
-	for (cfi_offset=0;
-	     cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
+	for (cfi_offset = 0; cfi_offset < ARRAY_SIZE(flash_offset_cfi);
 	     cfi_offset++) {
 		flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
 				 FLASH_CMD_CFI);
@@ -2336,7 +2335,7 @@
 #endif
 
 #if defined(CONFIG_SYS_FLASH_AUTOPROTECT_LIST)
-	for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
+	for (i = 0; i < ARRAY_SIZE(apl); i++) {
 		debug("autoprotecting from %08lx to %08lx\n",
 		      apl[i].start, apl[i].start + apl[i].size - 1);
 		flash_protect(FLAG_PROTECT_SET,
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 8821704..bb81e84 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -83,6 +83,7 @@
 else  # minimal SPL drivers
 
 COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
+COBJS-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand_spl.o
 
 endif # drivers
diff --git a/nand_spl/nand_boot_fsl_ifc.c b/drivers/mtd/nand/fsl_ifc_spl.c
similarity index 88%
rename from nand_spl/nand_boot_fsl_ifc.c
rename to drivers/mtd/nand/fsl_ifc_spl.c
index 44972c5..8537c4c 100644
--- a/nand_spl/nand_boot_fsl_ifc.c
+++ b/drivers/mtd/nand/fsl_ifc_spl.c
@@ -1,5 +1,5 @@
 /*
- * NAND boot for FSL Integrated Flash Controller, NAND Flash Control Machine
+ * NAND boot for Freescale Integrated Flash Controller, NAND FCM
  *
  * Copyright 2011 Freescale Semiconductor, Inc.
  * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
@@ -46,9 +46,9 @@
 				 unsigned int bufnum, int page_size)
 {
 	u32 reg = eccstat[bufnum / 4];
-	int errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
+	int errors = (reg >> ((3 - bufnum % 4) * 8)) & 0xf;
 
-	if (errors == 15) { /* uncorrectable */
+	if (errors == 0xf) { /* uncorrectable */
 		/* Blank pages fail hw ECC checks */
 		if (is_blank(buf, page_size))
 			return 1;
@@ -123,30 +123,17 @@
 	csor = CONFIG_SYS_NAND_CSOR;
 	cspr = CONFIG_SYS_NAND_CSPR;
 
-	if (!(csor & CSOR_NAND_ECC_DEC_EN)) {
-		/* soft ECC in SPL is unimplemented */
-		puts("WARNING: soft ECC not checked in SPL\n");
-	} else {
-		u32 hwcsor;
-
-		/* make sure board is configured with ECC on boot */
-		hwcsor = in_be32(&ifc->csor_cs[0].csor);
-		if (!(hwcsor & CSOR_NAND_ECC_DEC_EN))
-			puts("WARNING: ECC not checked in SPL, "
-				"check board cfg\n");
-	}
-
 	port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
 
 	if (csor & CSOR_NAND_PGS_4K) {
 		page_size = 4096;
-		bufnum_mask = 1;
+		bufnum_mask = 0x1;
 	} else if (csor & CSOR_NAND_PGS_2K) {
 		page_size = 2048;
-		bufnum_mask = 3;
+		bufnum_mask = 0x3;
 	} else {
 		page_size = 512;
-		bufnum_mask = 15;
+		bufnum_mask = 0xf;
 
 		if (port_size == 8)
 			bad_marker = 5;
@@ -174,8 +161,8 @@
 		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
 
 		out_be32(&ifc->ifc_nand.nand_fcr0,
-			(NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
-			(NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+			 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+			 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
 	} else {
 		out_be32(&ifc->ifc_nand.nand_fir0,
 			 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@@ -185,7 +172,7 @@
 		out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
 
 		out_be32(&ifc->ifc_nand.nand_fcr0,
-			NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+			 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
 	}
 
 	/* Program FBCR = 0 for full page read */
@@ -206,7 +193,7 @@
 			out_be32(&ifc->ifc_nand.col0, 0);
 			/* start read */
 			out_be32(&ifc->ifc_nand.nandseq_strt,
-				IFC_NAND_SEQ_STRT_FIR_STRT);
+				 IFC_NAND_SEQ_STRT_FIR_STRT);
 
 			/* wait for read to complete */
 			nand_wait(&buf[sram_addr], bufnum, page_size);
@@ -241,7 +228,6 @@
 void nand_boot(void)
 {
 	__attribute__((noreturn)) void (*uboot)(void);
-
 	/*
 	 * Load U-Boot image from NAND into RAM
 	 */
@@ -257,15 +243,16 @@
 		  (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
 #endif
 #endif
-
 	/*
 	 * Jump to U-Boot image
 	 */
+#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
 	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
 	uboot();
 }
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 90f8392..ecbb210 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -32,6 +32,7 @@
 COBJS-$(CONFIG_SPI_FLASH)	+= spi_flash.o
 COBJS-$(CONFIG_SPI_FLASH_ATMEL)	+= atmel.o
 COBJS-$(CONFIG_SPI_FLASH_EON)	+= eon.o
+COBJS-$(CONFIG_SPI_FLASH_GIGADEVICE)	+= gigadevice.o
 COBJS-$(CONFIG_SPI_FLASH_MACRONIX)	+= macronix.o
 COBJS-$(CONFIG_SPI_FLASH_SPANSION)	+= spansion.o
 COBJS-$(CONFIG_SPI_FLASH_SST)	+= sst.o
diff --git a/drivers/mtd/spi/gigadevice.c b/drivers/mtd/spi/gigadevice.c
new file mode 100644
index 0000000..b5e1ebe
--- /dev/null
+++ b/drivers/mtd/spi/gigadevice.c
@@ -0,0 +1,81 @@
+/*
+ * Gigadevice SPI flash driver
+ * Copyright 2013, Samsung Electronics Co., Ltd.
+ * Author: Banajit Goswami <banajit.g@samsung.com>
+ *
+ * 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 <malloc.h>
+#include <spi_flash.h>
+
+#include "spi_flash_internal.h"
+
+struct gigadevice_spi_flash_params {
+	uint16_t	id;
+	uint16_t	nr_blocks;
+	const char	*name;
+};
+
+static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
+	{
+		.id			= 0x6016,
+		.nr_blocks		= 64,
+		.name			= "GD25LQ",
+	},
+	{
+		.id			= 0x4017,
+		.nr_blocks		= 128,
+		.name			= "GD25Q64B",
+	},
+};
+
+struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
+{
+	const struct gigadevice_spi_flash_params *params;
+	struct spi_flash *flash;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) {
+		params = &gigadevice_spi_flash_table[i];
+		if (params->id == ((idcode[1] << 8) | idcode[2]))
+			break;
+	}
+
+	if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) {
+		debug("SF: Unsupported Gigadevice ID %02x%02x\n",
+				idcode[1], idcode[2]);
+		return NULL;
+	}
+
+	flash = spi_flash_alloc_base(spi, params->name);
+	if (!flash) {
+		debug("SF: Failed to allocate memory\n");
+		return NULL;
+	}
+	/* page_size */
+	flash->page_size = 256;
+	/* sector_size = page_size * pages_per_sector */
+	flash->sector_size = flash->page_size * 16;
+	/* size = sector_size * sector_per_block * number of blocks */
+	flash->size = flash->sector_size * 16 * params->nr_blocks;
+
+	return flash;
+}
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index b3ef90f..3ec2151 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -101,7 +101,7 @@
 		.idcode2 = 0x4d01,
 		.pages_per_sector = 256,
 		.nr_sectors = 256,
-		.name = "S25FL129P_64K/S25FL128S",
+		.name = "S25FL129P_64K/S25FL128S_64K",
 	},
 	{
 		.idcode1 = 0x0219,
@@ -110,6 +110,13 @@
 		.nr_sectors = 512,
 		.name = "S25FL256S_64K",
 	},
+	{
+		.idcode1 = 0x0220,
+		.idcode2 = 0x4d01,
+		.pages_per_sector = 256,
+		.nr_sectors = 1024,
+		.name = "S25FL512S_64K",
+	},
 };
 
 struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 0e38f59..6a6fe37 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -68,108 +68,25 @@
 	return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
 }
 
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
-		size_t len, const void *buf)
-{
-	unsigned long page_addr, byte_addr, page_size;
-	size_t chunk_len, actual;
-	int ret;
-	u8 cmd[4];
-
-	page_size = flash->page_size;
-	page_addr = offset / page_size;
-	byte_addr = offset % page_size;
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: unable to claim SPI bus\n");
-		return ret;
-	}
-
-	cmd[0] = CMD_PAGE_PROGRAM;
-	for (actual = 0; actual < len; actual += chunk_len) {
-		chunk_len = min(len - actual, page_size - byte_addr);
-
-		if (flash->spi->max_write_size)
-			chunk_len = min(chunk_len, flash->spi->max_write_size);
-
-		cmd[1] = page_addr >> 8;
-		cmd[2] = page_addr;
-		cmd[3] = byte_addr;
-
-		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
-		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
-		ret = spi_flash_cmd_write_enable(flash);
-		if (ret < 0) {
-			debug("SF: enabling write failed\n");
-			break;
-		}
-
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4,
-					  buf + actual, chunk_len);
-		if (ret < 0) {
-			debug("SF: write failed\n");
-			break;
-		}
-
-		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-		if (ret)
-			break;
-
-		byte_addr += chunk_len;
-		if (byte_addr == page_size) {
-			page_addr++;
-			byte_addr = 0;
-		}
-	}
-
-	spi_release_bus(flash->spi);
-	return ret;
-}
-
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len)
-{
-	struct spi_slave *spi = flash->spi;
-	int ret;
-
-	spi_claim_bus(spi);
-	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
-	spi_release_bus(spi);
-
-	return ret;
-}
-
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
-		size_t len, void *data)
-{
-	u8 cmd[5];
-
-	/* Handle memory-mapped SPI */
-	if (flash->memory_map) {
-		memcpy(data, flash->memory_map + offset, len);
-		return 0;
-	}
-
-	cmd[0] = CMD_READ_ARRAY_FAST;
-	spi_flash_addr(offset, cmd);
-	cmd[4] = 0x00;
-
-	return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len);
-}
-
-int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
-			   u8 cmd, u8 poll_bit)
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
 {
 	struct spi_slave *spi = flash->spi;
 	unsigned long timebase;
 	int ret;
 	u8 status;
+	u8 check_status = 0x0;
+	u8 poll_bit = STATUS_WIP;
+	u8 cmd = flash->poll_cmd;
+
+	if (cmd == CMD_FLAG_STATUS) {
+		poll_bit = STATUS_PEC;
+		check_status = poll_bit;
+	}
 
 	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
 	if (ret) {
-		debug("SF: Failed to send command %02x: %d\n", cmd, ret);
+		debug("SF: fail to read %s status register\n",
+			cmd == CMD_READ_STATUS ? "read" : "flag");
 		return ret;
 	}
 
@@ -181,14 +98,14 @@
 		if (ret)
 			return -1;
 
-		if ((status & poll_bit) == 0)
+		if ((status & poll_bit) == check_status)
 			break;
 
 	} while (get_timer(timebase) < timeout);
 
 	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
 
-	if ((status & poll_bit) == 0)
+	if ((status & poll_bit) == check_status)
 		return 0;
 
 	/* Timed out */
@@ -196,17 +113,52 @@
 	return -1;
 }
 
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
+		size_t cmd_len, const void *buf, size_t buf_len)
 {
-	return spi_flash_cmd_poll_bit(flash, timeout,
-		CMD_READ_STATUS, STATUS_WIP);
+	struct spi_slave *spi = flash->spi;
+	unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
+	int ret;
+
+	if (buf == NULL)
+		timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret) {
+		debug("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_write_enable(flash);
+	if (ret < 0) {
+		debug("SF: enabling write failed\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
+	if (ret < 0) {
+		debug("SF: write cmd failed\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_wait_ready(flash, timeout);
+	if (ret < 0) {
+		debug("SF: write %s timed out\n",
+			timeout == SPI_FLASH_PROG_TIMEOUT ?
+			"program" : "page erase");
+		return ret;
+	}
+
+	spi_release_bus(spi);
+
+	return ret;
 }
 
 int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
-	u32 end, erase_size;
-	int ret;
+	u32 erase_size;
 	u8 cmd[4];
+	int ret = -1;
 
 	erase_size = flash->sector_size;
 	if (offset % erase_size || len % erase_size) {
@@ -214,40 +166,157 @@
 		return -1;
 	}
 
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: Unable to claim SPI bus\n");
-		return ret;
-	}
-
 	if (erase_size == 4096)
 		cmd[0] = CMD_ERASE_4K;
 	else
 		cmd[0] = CMD_ERASE_64K;
-	end = offset + len;
 
-	while (offset < end) {
+	while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+		u8 bank_sel;
+
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+#endif
 		spi_flash_addr(offset, cmd);
-		offset += erase_size;
 
 		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
 		      cmd[2], cmd[3], offset);
 
-		ret = spi_flash_cmd_write_enable(flash);
-		if (ret)
-			goto out;
+		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
+		if (ret < 0) {
+			debug("SF: erase failed\n");
+			break;
+		}
 
-		ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0);
-		if (ret)
-			goto out;
-
-		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-		if (ret)
-			goto out;
+		offset += erase_size;
+		len -= erase_size;
 	}
 
- out:
-	spi_release_bus(flash->spi);
+	return ret;
+}
+
+int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
+		size_t len, const void *buf)
+{
+	unsigned long byte_addr, page_size;
+	size_t chunk_len, actual;
+	u8 cmd[4];
+	int ret = -1;
+
+	page_size = flash->page_size;
+
+	cmd[0] = CMD_PAGE_PROGRAM;
+	for (actual = 0; actual < len; actual += chunk_len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+		u8 bank_sel;
+
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+#endif
+		byte_addr = offset % page_size;
+		chunk_len = min(len - actual, page_size - byte_addr);
+
+		if (flash->spi->max_write_size)
+			chunk_len = min(chunk_len, flash->spi->max_write_size);
+
+		spi_flash_addr(offset, cmd);
+
+		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
+		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+
+		ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
+					buf + actual, chunk_len);
+		if (ret < 0) {
+			debug("SF: write failed\n");
+			break;
+		}
+
+		offset += chunk_len;
+	}
+
+	return ret;
+}
+
+int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
+		size_t cmd_len, void *data, size_t data_len)
+{
+	struct spi_slave *spi = flash->spi;
+	int ret;
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret) {
+		debug("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
+	if (ret < 0) {
+		debug("SF: read cmd failed\n");
+		return ret;
+	}
+
+	spi_release_bus(spi);
+
+	return ret;
+}
+
+int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
+		size_t len, void *data)
+{
+	u8 cmd[5], bank_sel = 0;
+	u32 remain_len, read_len;
+	int ret = -1;
+
+	/* Handle memory-mapped SPI */
+	if (flash->memory_map) {
+		memcpy(data, flash->memory_map + offset, len);
+		return 0;
+	}
+
+	cmd[0] = CMD_READ_ARRAY_FAST;
+	cmd[4] = 0x00;
+
+	while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+#endif
+		remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
+		if (len < remain_len)
+			read_len = len;
+		else
+			read_len = remain_len;
+
+		spi_flash_addr(offset, cmd);
+
+		ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
+							data, read_len);
+		if (ret < 0) {
+			debug("SF: read failed\n");
+			break;
+		}
+
+		offset += read_len;
+		len -= read_len;
+		data += read_len;
+	}
+
 	return ret;
 }
 
@@ -256,28 +325,75 @@
 	u8 cmd;
 	int ret;
 
-	ret = spi_flash_cmd_write_enable(flash);
-	if (ret < 0) {
-		debug("SF: enabling write failed\n");
-		return ret;
-	}
-
 	cmd = CMD_WRITE_STATUS;
-	ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1);
-	if (ret) {
-		debug("SF: fail to write status register\n");
-		return ret;
-	}
-
-	ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+	ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
 	if (ret < 0) {
-		debug("SF: write status register timed out\n");
+		debug("SF: fail to write status register\n");
 		return ret;
 	}
 
 	return 0;
 }
 
+#ifdef CONFIG_SPI_FLASH_BAR
+int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
+{
+	u8 cmd;
+	int ret;
+
+	if (flash->bank_curr == bank_sel) {
+		debug("SF: not require to enable bank%d\n", bank_sel);
+		return 0;
+	}
+
+	cmd = flash->bank_write_cmd;
+	ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
+	if (ret < 0) {
+		debug("SF: fail to write bank register\n");
+		return ret;
+	}
+	flash->bank_curr = bank_sel;
+
+	return 0;
+}
+
+int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0)
+{
+	u8 cmd;
+	u8 curr_bank = 0;
+
+	/* discover bank cmds */
+	switch (idcode0) {
+	case SPI_FLASH_SPANSION_IDCODE0:
+		flash->bank_read_cmd = CMD_BANKADDR_BRRD;
+		flash->bank_write_cmd = CMD_BANKADDR_BRWR;
+		break;
+	case SPI_FLASH_STMICRO_IDCODE0:
+	case SPI_FLASH_WINBOND_IDCODE0:
+		flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
+		flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
+		break;
+	default:
+		printf("SF: Unsupported bank commands %02x\n", idcode0);
+		return -1;
+	}
+
+	/* read the bank reg - on which bank the flash is in currently */
+	cmd = flash->bank_read_cmd;
+	if (flash->size > SPI_FLASH_16MB_BOUN) {
+		if (spi_flash_read_common(flash, &cmd, 1, &curr_bank, 1)) {
+			debug("SF: fail to read bank addr register\n");
+			return -1;
+		}
+		flash->bank_curr = curr_bank;
+	} else {
+		flash->bank_curr = curr_bank;
+	}
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_OF_CONTROL
 int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
 {
@@ -342,6 +458,9 @@
 #ifdef CONFIG_SPI_FLASH_EON
 	{ 0, 0x1c, spi_flash_probe_eon, },
 #endif
+#ifdef CONFIG_SPI_FLASH_GIGADEVICE
+	{ 0, 0xc8, spi_flash_probe_gigadevice, },
+#endif
 #ifdef CONFIG_SPI_FLASH_MACRONIX
 	{ 0, 0xc2, spi_flash_probe_macronix, },
 #endif
@@ -422,6 +541,13 @@
 		goto err_manufacturer_probe;
 	}
 
+#ifdef CONFIG_SPI_FLASH_BAR
+	/* Configure the BAR - disover bank cmds and read current bank  */
+	ret = spi_flash_bank_config(flash, *idp);
+	if (ret < 0)
+		goto err_manufacturer_probe;
+#endif
+
 #ifdef CONFIG_OF_CONTROL
 	if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
 		debug("SF: FDT decode error\n");
@@ -434,6 +560,12 @@
 	if (flash->memory_map)
 		printf(", mapped at %p", flash->memory_map);
 	puts("\n");
+#ifndef CONFIG_SPI_FLASH_BAR
+	if (flash->size > SPI_FLASH_16MB_BOUN) {
+		puts("SF: Warning - Only lower 16MiB accessible,");
+		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
+	}
+#endif
 
 	spi_release_bus(spi);
 
@@ -464,6 +596,7 @@
 	/* Set up some basic fields - caller will sort out sizes */
 	flash->spi = spi;
 	flash->name = name;
+	flash->poll_cmd = CMD_READ_STATUS;
 
 	flash->read = spi_flash_cmd_read_fast;
 	flash->write = spi_flash_cmd_write_multi;
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index 141cfa8..af1afa9 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -22,14 +22,31 @@
 #define CMD_PAGE_PROGRAM		0x02
 #define CMD_WRITE_DISABLE		0x04
 #define CMD_READ_STATUS			0x05
+#define CMD_FLAG_STATUS			0x70
 #define CMD_WRITE_ENABLE		0x06
 #define CMD_ERASE_4K			0x20
 #define CMD_ERASE_32K			0x52
 #define CMD_ERASE_64K			0xd8
 #define CMD_ERASE_CHIP			0xc7
 
+#define SPI_FLASH_16MB_BOUN		0x1000000
+
+/* Manufacture ID's */
+#define SPI_FLASH_SPANSION_IDCODE0	0x01
+#define SPI_FLASH_STMICRO_IDCODE0	0x20
+#define SPI_FLASH_WINBOND_IDCODE0	0xef
+
+#ifdef CONFIG_SPI_FLASH_BAR
+/* Bank addr access commands */
+# define CMD_BANKADDR_BRWR		0x17
+# define CMD_BANKADDR_BRRD		0x16
+# define CMD_EXTNADDR_WREAR		0xC5
+# define CMD_EXTNADDR_RDEAR		0xC8
+#endif
+
 /* Common status */
 #define STATUS_WIP			0x01
+#define STATUS_PEC			0x80
 
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
@@ -77,16 +94,30 @@
 /* Program the status register. */
 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
 
+#ifdef CONFIG_SPI_FLASH_BAR
+/* Program the bank address register */
+int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel);
+
+/* Configure the BAR - discover the bank cmds */
+int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0);
+#endif
+
 /*
  * Same as spi_flash_cmd_read() except it also claims/releases the SPI
  * bus. Used as common part of the ->read() operation.
  */
 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
 		size_t cmd_len, void *data, size_t data_len);
-
-/* Send a command to the device and wait for some bit to clear itself. */
-int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
-			   u8 cmd, u8 poll_bit);
+/*
+ * Used for spi_flash write operation
+ * - SPI claim
+ * - spi_flash_cmd_write_enable
+ * - spi_flash_cmd_write
+ * - spi_flash_cmd_wait_ready
+ * - SPI release
+ */
+int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
+		size_t cmd_len, const void *buf, size_t buf_len);
 
 /*
  * Send the read status command to the device and wait for the wip
@@ -106,3 +137,4 @@
 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode);
 struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode);
 struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode);
+struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode);
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index 2a9972b..7e41ee1 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -140,6 +140,30 @@
 		.nr_sectors = 512,
 		.name = "N25Q256A",
 	},
+	{
+		.id = 0xba20,
+		.pages_per_sector = 256,
+		.nr_sectors = 1024,
+		.name = "N25Q512",
+	},
+	{
+		.id = 0xbb20,
+		.pages_per_sector = 256,
+		.nr_sectors = 1024,
+		.name = "N25Q512A",
+	},
+	{
+		.id = 0xba21,
+		.pages_per_sector = 256,
+		.nr_sectors = 2048,
+		.name = "N25Q1024",
+	},
+	{
+		.id = 0xbb21,
+		.pages_per_sector = 256,
+		.nr_sectors = 2048,
+		.name = "N25Q1024A",
+	},
 };
 
 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
@@ -186,5 +210,9 @@
 	flash->sector_size = 256 * params->pages_per_sector;
 	flash->size = flash->sector_size * params->nr_sectors;
 
+	/* for >= 512MiB flashes, use flag status instead of read_status */
+	if (flash->size >= 0x4000000)
+		flash->poll_cmd = CMD_FLAG_STATUS;
+
 	return flash;
 }
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index 8457808..c399bf1 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -55,27 +55,27 @@
 	{
 		.id			= 0x4014,
 		.nr_blocks		= 16,
-		.name			= "W25Q80BL",
+		.name			= "W25Q80BL/W25Q80BV",
 	},
 	{
 		.id			= 0x4015,
 		.nr_blocks		= 32,
-		.name			= "W25Q16",
+		.name			= "W25Q16CL/W25Q16DV",
 	},
 	{
 		.id			= 0x4016,
 		.nr_blocks		= 64,
-		.name			= "W25Q32",
+		.name			= "W25Q32BV/W25Q32FV_SPI",
 	},
 	{
 		.id			= 0x4017,
 		.nr_blocks		= 128,
-		.name			= "W25Q64",
+		.name			= "W25Q64CV/W25Q64FV_SPI",
 	},
 	{
 		.id			= 0x4018,
 		.nr_blocks		= 256,
-		.name			= "W25Q128",
+		.name			= "W25Q128BV/W25Q128FV_SPI",
 	},
 	{
 		.id			= 0x4019,
@@ -88,14 +88,24 @@
 		.name			= "W25Q80BW",
 	},
 	{
+		.id			= 0x6015,
+		.nr_blocks		= 32,
+		.name			= "W25Q16DW",
+	},
+	{
 		.id			= 0x6016,
 		.nr_blocks		= 64,
-		.name			= "W25Q32DW",
+		.name			= "W25Q32DW/W25Q32FV_QPI",
 	},
 	{
 		.id			= 0x6017,
 		.nr_blocks		= 128,
-		.name			= "W25Q64DW",
+		.name			= "W25Q64DW/W25Q64FV_QPI",
+	},
+	{
+		.id			= 0x6018,
+		.nr_blocks		= 256,
+		.name			= "W25Q128FW/W25Q128FV_QPI",
 	},
 };
 
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 786a656..9cf2983 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -46,10 +46,12 @@
 COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o
 COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
 COBJS-$(CONFIG_FTGMAC100) += ftgmac100.o
+COBJS-$(CONFIG_FTMAC110) += ftmac110.o
 COBJS-$(CONFIG_FTMAC100) += ftmac100.o
 COBJS-$(CONFIG_GRETH) += greth.o
 COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
 COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
+COBJS-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 COBJS-$(CONFIG_LAN91C96) += lan91c96.o
 COBJS-$(CONFIG_MACB) += macb.o
 COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
@@ -68,6 +70,7 @@
 COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
 COBJS-$(CONFIG_SMC91111) += smc91111.o
 COBJS-$(CONFIG_SMC911X) += smc911x.o
+COBJS-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
 COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 COBJS-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index bf21a08..46f6601 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -113,7 +113,9 @@
 	int timeout = CONFIG_MACRESET_TIMEOUT;
 
 	writel(DMAMAC_SRST, &dma_p->busmode);
-	writel(MII_PORTSELECT, &mac_p->conf);
+
+	if (priv->interface != PHY_INTERFACE_MODE_RGMII)
+		writel(MII_PORTSELECT, &mac_p->conf);
 
 	start = get_timer(0);
 	while (get_timer(start) < timeout) {
diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c
index 69ba57d..2dbb328 100644
--- a/drivers/net/ftgmac100.c
+++ b/drivers/net/ftgmac100.c
@@ -27,11 +27,13 @@
 #include <malloc.h>
 #include <net.h>
 #include <asm/io.h>
+#include <asm/dma-mapping.h>
 #include <linux/mii.h>
 
 #include "ftgmac100.h"
 
 #define ETH_ZLEN	60
+#define CFG_XBUF_SIZE	1536
 
 /* RBSR - hw default init value is also 0x640 */
 #define RBSR_DEFAULT_VALUE	0x640
@@ -40,8 +42,10 @@
 #define PKTBUFSTX	4	/* must be power of 2 */
 
 struct ftgmac100_data {
-	struct ftgmac100_txdes txdes[PKTBUFSTX];
-	struct ftgmac100_rxdes rxdes[PKTBUFSRX];
+	ulong txdes_dma;
+	struct ftgmac100_txdes *txdes;
+	ulong rxdes_dma;
+	struct ftgmac100_rxdes *rxdes;
 	int tx_index;
 	int rx_index;
 	int phy_addr;
@@ -375,13 +379,34 @@
 {
 	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
 	struct ftgmac100_data *priv = dev->priv;
-	struct ftgmac100_txdes *txdes = priv->txdes;
-	struct ftgmac100_rxdes *rxdes = priv->rxdes;
+	struct ftgmac100_txdes *txdes;
+	struct ftgmac100_rxdes *rxdes;
 	unsigned int maccr;
+	void *buf;
 	int i;
 
 	debug("%s()\n", __func__);
 
+	if (!priv->txdes) {
+		txdes = dma_alloc_coherent(
+			sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
+		if (!txdes)
+			panic("ftgmac100: out of memory\n");
+		memset(txdes, 0, sizeof(*txdes) * PKTBUFSTX);
+		priv->txdes = txdes;
+	}
+	txdes = priv->txdes;
+
+	if (!priv->rxdes) {
+		rxdes = dma_alloc_coherent(
+			sizeof(*rxdes) * PKTBUFSRX, &priv->rxdes_dma);
+		if (!rxdes)
+			panic("ftgmac100: out of memory\n");
+		memset(rxdes, 0, sizeof(*rxdes) * PKTBUFSRX);
+		priv->rxdes = rxdes;
+	}
+	rxdes = priv->rxdes;
+
 	/* set the ethernet address */
 	ftgmac100_set_mac_from_env(dev);
 
@@ -397,21 +422,31 @@
 
 	for (i = 0; i < PKTBUFSTX; i++) {
 		/* TXBUF_BADR */
-		txdes[i].txdes3 = 0;
+		if (!txdes[i].txdes2) {
+			buf = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
+			if (!buf)
+				panic("ftgmac100: out of memory\n");
+			txdes[i].txdes3 = virt_to_phys(buf);
+			txdes[i].txdes2 = (uint)buf;
+		}
 		txdes[i].txdes1 = 0;
 	}
 
 	for (i = 0; i < PKTBUFSRX; i++) {
 		/* RXBUF_BADR */
-		rxdes[i].rxdes3 = (unsigned int)NetRxPackets[i];
+		if (!rxdes[i].rxdes2) {
+			buf = NetRxPackets[i];
+			rxdes[i].rxdes3 = virt_to_phys(buf);
+			rxdes[i].rxdes2 = (uint)buf;
+		}
 		rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
 	}
 
 	/* transmit ring */
-	writel((unsigned int)txdes, &ftgmac100->txr_badr);
+	writel(priv->txdes_dma, &ftgmac100->txr_badr);
 
 	/* receive ring */
-	writel((unsigned int)rxdes, &ftgmac100->rxr_badr);
+	writel(priv->rxdes_dma, &ftgmac100->rxr_badr);
 
 	/* poll receive descriptor automatically */
 	writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
@@ -466,8 +501,11 @@
 	debug("%s(): RX buffer %d, %x received\n",
 	       __func__, priv->rx_index, rxlen);
 
+	/* invalidate d-cache */
+	dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);
+
 	/* pass the packet up to the protocol layers. */
-	NetReceive((void *)curr_des->rxdes3, rxlen);
+	NetReceive((void *)curr_des->rxdes2, rxlen);
 
 	/* release buffer to DMA */
 	curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
@@ -485,7 +523,6 @@
 	struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
 	struct ftgmac100_data *priv = dev->priv;
 	struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
-	int start;
 
 	if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
 		debug("%s(): no TX descriptor available\n", __func__);
@@ -496,8 +533,8 @@
 
 	length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
 
-	/* initiate a transmit sequence */
-	curr_des->txdes3 = (unsigned int)packet;	/* TXBUF_BADR */
+	memcpy((void *)curr_des->txdes2, (void *)packet, length);
+	dma_map_single((void *)curr_des->txdes2, length, DMA_TO_DEVICE);
 
 	/* only one descriptor on TXBUF */
 	curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
@@ -509,15 +546,6 @@
 	/* start transmit */
 	writel(1, &ftgmac100->txpd);
 
-	/* wait for transfer to succeed */
-	start = get_timer(0);
-	while (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
-		if (get_timer(0) >= 5) {
-			debug("%s(): timed out\n", __func__);
-			return -1;
-		}
-	}
-
 	debug("%s(): packet sent\n", __func__);
 
 	priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c
new file mode 100644
index 0000000..579dcc7
--- /dev/null
+++ b/drivers/net/ftmac110.c
@@ -0,0 +1,473 @@
+/*
+ * Faraday 10/100Mbps Ethernet Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <net.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/dma-mapping.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+#include "ftmac110.h"
+
+#define CFG_RXDES_NUM   8
+#define CFG_TXDES_NUM   2
+#define CFG_XBUF_SIZE   1536
+
+#define CFG_MDIORD_TIMEOUT  (CONFIG_SYS_HZ >> 1) /* 500 ms */
+#define CFG_MDIOWR_TIMEOUT  (CONFIG_SYS_HZ >> 1) /* 500 ms */
+#define CFG_LINKUP_TIMEOUT  (CONFIG_SYS_HZ << 2) /* 4 sec */
+
+/*
+ * FTMAC110 DMA design issue
+ *
+ * Its DMA engine has a weird restriction that its Rx DMA engine
+ * accepts only 16-bits aligned address, 32-bits aligned is not
+ * acceptable. However this restriction does not apply to Tx DMA.
+ *
+ * Conclusion:
+ * (1) Tx DMA Buffer Address:
+ *     1 bytes aligned: Invalid
+ *     2 bytes aligned: O.K
+ *     4 bytes aligned: O.K (-> u-boot ZeroCopy is possible)
+ * (2) Rx DMA Buffer Address:
+ *     1 bytes aligned: Invalid
+ *     2 bytes aligned: O.K
+ *     4 bytes aligned: Invalid
+ */
+
+struct ftmac110_chip {
+	void __iomem *regs;
+	uint32_t imr;
+	uint32_t maccr;
+	uint32_t lnkup;
+	uint32_t phy_addr;
+
+	struct ftmac110_rxd *rxd;
+	ulong                rxd_dma;
+	uint32_t             rxd_idx;
+
+	struct ftmac110_txd *txd;
+	ulong                txd_dma;
+	uint32_t             txd_idx;
+};
+
+static int ftmac110_reset(struct eth_device *dev);
+
+static uint16_t mdio_read(struct eth_device *dev,
+	uint8_t phyaddr, uint8_t phyreg)
+{
+	struct ftmac110_chip *chip = dev->priv;
+	struct ftmac110_regs __iomem *regs = chip->regs;
+	uint32_t tmp, ts;
+	uint16_t ret = 0xffff;
+
+	tmp = PHYCR_READ
+		| (phyaddr << PHYCR_ADDR_SHIFT)
+		| (phyreg  << PHYCR_REG_SHIFT);
+
+	writel(tmp, &regs->phycr);
+
+	for (ts = get_timer(0); get_timer(ts) < CFG_MDIORD_TIMEOUT; ) {
+		tmp = readl(&regs->phycr);
+		if (tmp & PHYCR_READ)
+			continue;
+		break;
+	}
+
+	if (tmp & PHYCR_READ)
+		printf("ftmac110: mdio read timeout\n");
+	else
+		ret = (uint16_t)(tmp & 0xffff);
+
+	return ret;
+}
+
+static void mdio_write(struct eth_device *dev,
+	uint8_t phyaddr, uint8_t phyreg, uint16_t phydata)
+{
+	struct ftmac110_chip *chip = dev->priv;
+	struct ftmac110_regs __iomem *regs = chip->regs;
+	uint32_t tmp, ts;
+
+	tmp = PHYCR_WRITE
+		| (phyaddr << PHYCR_ADDR_SHIFT)
+		| (phyreg  << PHYCR_REG_SHIFT);
+
+	writel(phydata, &regs->phydr);
+	writel(tmp, &regs->phycr);
+
+	for (ts = get_timer(0); get_timer(ts) < CFG_MDIOWR_TIMEOUT; ) {
+		if (readl(&regs->phycr) & PHYCR_WRITE)
+			continue;
+		break;
+	}
+
+	if (readl(&regs->phycr) & PHYCR_WRITE)
+		printf("ftmac110: mdio write timeout\n");
+}
+
+static uint32_t ftmac110_phyqry(struct eth_device *dev)
+{
+	ulong ts;
+	uint32_t maccr;
+	uint16_t pa, tmp, bmsr, bmcr;
+	struct ftmac110_chip *chip = dev->priv;
+
+	/* Default = 100Mbps Full */
+	maccr = MACCR_100M | MACCR_FD;
+
+	/* 1. find the phy device  */
+	for (pa = 0; pa < 32; ++pa) {
+		tmp = mdio_read(dev, pa, MII_PHYSID1);
+		if (tmp == 0xFFFF || tmp == 0x0000)
+			continue;
+		chip->phy_addr = pa;
+		break;
+	}
+	if (pa >= 32) {
+		puts("ftmac110: phy device not found!\n");
+		goto exit;
+	}
+
+	/* 2. wait until link-up & auto-negotiation complete */
+	chip->lnkup = 0;
+	bmcr = mdio_read(dev, chip->phy_addr, MII_BMCR);
+	ts = get_timer(0);
+	do {
+		bmsr = mdio_read(dev, chip->phy_addr, MII_BMSR);
+		chip->lnkup = (bmsr & BMSR_LSTATUS) ? 1 : 0;
+		if (!chip->lnkup)
+			continue;
+		if (!(bmcr & BMCR_ANENABLE) || (bmsr & BMSR_ANEGCOMPLETE))
+			break;
+	} while (get_timer(ts) < CFG_LINKUP_TIMEOUT);
+	if (!chip->lnkup) {
+		puts("ftmac110: link down\n");
+		goto exit;
+	}
+	if (!(bmcr & BMCR_ANENABLE))
+		puts("ftmac110: auto negotiation disabled\n");
+	else if (!(bmsr & BMSR_ANEGCOMPLETE))
+		puts("ftmac110: auto negotiation timeout\n");
+
+	/* 3. derive MACCR */
+	if ((bmcr & BMCR_ANENABLE) && (bmsr & BMSR_ANEGCOMPLETE)) {
+		tmp  = mdio_read(dev, chip->phy_addr, MII_ADVERTISE);
+		tmp &= mdio_read(dev, chip->phy_addr, MII_LPA);
+		if (tmp & LPA_100FULL)      /* 100Mbps full-duplex */
+			maccr = MACCR_100M | MACCR_FD;
+		else if (tmp & LPA_100HALF) /* 100Mbps half-duplex */
+			maccr = MACCR_100M;
+		else if (tmp & LPA_10FULL)  /* 10Mbps full-duplex */
+			maccr = MACCR_FD;
+		else if (tmp & LPA_10HALF)  /* 10Mbps half-duplex */
+			maccr = 0;
+	} else {
+		if (bmcr & BMCR_SPEED100)
+			maccr = MACCR_100M;
+		else
+			maccr = 0;
+		if (bmcr & BMCR_FULLDPLX)
+			maccr |= MACCR_FD;
+	}
+
+exit:
+	printf("ftmac110: %d Mbps, %s\n",
+	       (maccr & MACCR_100M) ? 100 : 10,
+	       (maccr & MACCR_FD) ? "Full" : "half");
+	return maccr;
+}
+
+static int ftmac110_reset(struct eth_device *dev)
+{
+	uint8_t *a;
+	uint32_t i, maccr;
+	struct ftmac110_chip *chip = dev->priv;
+	struct ftmac110_regs __iomem *regs = chip->regs;
+
+	/* 1. MAC reset */
+	writel(MACCR_RESET, &regs->maccr);
+	for (i = get_timer(0); get_timer(i) < 1000; ) {
+		if (readl(&regs->maccr) & MACCR_RESET)
+			continue;
+		break;
+	}
+	if (readl(&regs->maccr) & MACCR_RESET) {
+		printf("ftmac110: reset failed\n");
+		return -ENXIO;
+	}
+
+	/* 1-1. Init tx ring */
+	for (i = 0; i < CFG_TXDES_NUM; ++i) {
+		/* owned by SW */
+		chip->txd[i].ct[0] = 0;
+	}
+	chip->txd_idx = 0;
+
+	/* 1-2. Init rx ring */
+	for (i = 0; i < CFG_RXDES_NUM; ++i) {
+		/* owned by HW */
+		chip->rxd[i].ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER);
+	}
+	chip->rxd_idx = 0;
+
+	/* 2. PHY status query */
+	maccr = ftmac110_phyqry(dev);
+
+	/* 3. Fix up the MACCR value */
+	chip->maccr = maccr | MACCR_CRCAPD | MACCR_RXALL | MACCR_RXRUNT
+		| MACCR_RXEN | MACCR_TXEN | MACCR_RXDMAEN | MACCR_TXDMAEN;
+
+	/* 4. MAC address setup */
+	a = dev->enetaddr;
+	writel(a[1] | (a[0] << 8), &regs->mac[0]);
+	writel(a[5] | (a[4] << 8) | (a[3] << 16)
+		| (a[2] << 24), &regs->mac[1]);
+
+	/* 5. MAC registers setup */
+	writel(chip->rxd_dma, &regs->rxba);
+	writel(chip->txd_dma, &regs->txba);
+	/* interrupt at each tx/rx */
+	writel(ITC_DEFAULT, &regs->itc);
+	/* no tx pool, rx poll = 1 normal cycle */
+	writel(APTC_DEFAULT, &regs->aptc);
+	/* rx threshold = [6/8 fifo, 2/8 fifo] */
+	writel(DBLAC_DEFAULT, &regs->dblac);
+	/* disable & clear all interrupt status */
+	chip->imr = 0;
+	writel(ISR_ALL, &regs->isr);
+	writel(chip->imr, &regs->imr);
+	/* enable mac */
+	writel(chip->maccr, &regs->maccr);
+
+	return 0;
+}
+
+static int ftmac110_probe(struct eth_device *dev, bd_t *bis)
+{
+	debug("ftmac110: probe\n");
+
+	if (ftmac110_reset(dev))
+		return -1;
+
+	return 0;
+}
+
+static void ftmac110_halt(struct eth_device *dev)
+{
+	struct ftmac110_chip *chip = dev->priv;
+	struct ftmac110_regs __iomem *regs = chip->regs;
+
+	writel(0, &regs->imr);
+	writel(0, &regs->maccr);
+
+	debug("ftmac110: halt\n");
+}
+
+static int ftmac110_send(struct eth_device *dev, void *pkt, int len)
+{
+	struct ftmac110_chip *chip = dev->priv;
+	struct ftmac110_regs __iomem *regs = chip->regs;
+	struct ftmac110_txd *des;
+
+	if (!chip->lnkup)
+		return 0;
+
+	if (len <= 0 || len > CFG_XBUF_SIZE) {
+		printf("ftmac110: bad tx pkt len(%d)\n", len);
+		return 0;
+	}
+
+	len = max(60, len);
+
+	des = &chip->txd[chip->txd_idx];
+	if (le32_to_cpu(des->ct[0]) & FTMAC110_TXCT0_OWNER) {
+		/* kick-off Tx DMA */
+		writel(0xffffffff, &regs->txpd);
+		printf("ftmac110: out of txd\n");
+		return 0;
+	}
+
+	memcpy(des->vbuf, (void *)pkt, len);
+	dma_map_single(des->vbuf, len, DMA_TO_DEVICE);
+
+	/* update len, fts and lts */
+	des->ct[1] &= cpu_to_le32(FTMAC110_TXCT1_END);
+	des->ct[1] |= cpu_to_le32(FTMAC110_TXCT1_LEN(len)
+		| FTMAC110_TXCT1_FTS | FTMAC110_TXCT1_LTS);
+
+	/* set owner bit and clear others */
+	des->ct[0] = cpu_to_le32(FTMAC110_TXCT0_OWNER);
+
+	/* kick-off Tx DMA */
+	writel(0xffffffff, &regs->txpd);
+
+	chip->txd_idx = (chip->txd_idx + 1) % CFG_TXDES_NUM;
+
+	return len;
+}
+
+static int ftmac110_recv(struct eth_device *dev)
+{
+	struct ftmac110_chip *chip = dev->priv;
+	struct ftmac110_rxd *des;
+	uint32_t ct0, len, rlen = 0;
+	uint8_t *buf;
+
+	if (!chip->lnkup)
+		return 0;
+
+	do {
+		des = &chip->rxd[chip->rxd_idx];
+		ct0 = le32_to_cpu(des->ct[0]);
+		if (ct0 & FTMAC110_RXCT0_OWNER)
+			break;
+
+		len = FTMAC110_RXCT0_LEN(ct0);
+		buf = des->vbuf;
+
+		if (ct0 & FTMAC110_RXCT0_ERRMASK) {
+			printf("ftmac110: rx error\n");
+		} else {
+			dma_map_single(buf, len, DMA_FROM_DEVICE);
+			NetReceive(buf, len);
+			rlen += len;
+		}
+
+		/* owned by hardware */
+		des->ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER);
+
+		chip->rxd_idx = (chip->rxd_idx + 1) % CFG_RXDES_NUM;
+	} while (0);
+
+	return rlen;
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+
+static int ftmac110_mdio_read(
+	const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
+{
+	int ret = 0;
+	struct eth_device *dev;
+
+	dev = eth_get_dev_by_name(devname);
+	if (dev == NULL) {
+		printf("%s: no such device\n", devname);
+		ret = -1;
+	} else {
+		*value = mdio_read(dev, addr, reg);
+	}
+
+	return ret;
+}
+
+static int ftmac110_mdio_write(
+	const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
+{
+	int ret = 0;
+	struct eth_device *dev;
+
+	dev = eth_get_dev_by_name(devname);
+	if (dev == NULL) {
+		printf("%s: no such device\n", devname);
+		ret = -1;
+	} else {
+		mdio_write(dev, addr, reg, value);
+	}
+
+	return ret;
+}
+
+#endif    /* #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */
+
+int ftmac110_initialize(bd_t *bis)
+{
+	int i, card_nr = 0;
+	struct eth_device *dev;
+	struct ftmac110_chip *chip;
+
+	dev = malloc(sizeof(*dev) + sizeof(*chip));
+	if (dev == NULL) {
+		panic("ftmac110: out of memory 1\n");
+		return -1;
+	}
+	chip = (struct ftmac110_chip *)(dev + 1);
+	memset(dev, 0, sizeof(*dev) + sizeof(*chip));
+
+	sprintf(dev->name, "FTMAC110#%d", card_nr);
+
+	dev->iobase = CONFIG_FTMAC110_BASE;
+	chip->regs = (void __iomem *)dev->iobase;
+	dev->priv = chip;
+	dev->init = ftmac110_probe;
+	dev->halt = ftmac110_halt;
+	dev->send = ftmac110_send;
+	dev->recv = ftmac110_recv;
+
+	if (!eth_getenv_enetaddr_by_index("eth", card_nr, dev->enetaddr))
+		eth_random_enetaddr(dev->enetaddr);
+
+	/* allocate tx descriptors (it must be 16 bytes aligned) */
+	chip->txd = dma_alloc_coherent(
+		sizeof(struct ftmac110_txd) * CFG_TXDES_NUM, &chip->txd_dma);
+	if (!chip->txd)
+		panic("ftmac110: out of memory 3\n");
+	memset(chip->txd, 0,
+	       sizeof(struct ftmac110_txd) * CFG_TXDES_NUM);
+	for (i = 0; i < CFG_TXDES_NUM; ++i) {
+		void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
+		if (!va)
+			panic("ftmac110: out of memory 4\n");
+		chip->txd[i].vbuf  = va;
+		chip->txd[i].buf   = cpu_to_le32(virt_to_phys(va));
+		chip->txd[i].ct[1] = 0;
+		chip->txd[i].ct[0] = 0; /* owned by SW */
+	}
+	chip->txd[i - 1].ct[1] |= cpu_to_le32(FTMAC110_TXCT1_END);
+	chip->txd_idx = 0;
+
+	/* allocate rx descriptors (it must be 16 bytes aligned) */
+	chip->rxd = dma_alloc_coherent(
+		sizeof(struct ftmac110_rxd) * CFG_RXDES_NUM, &chip->rxd_dma);
+	if (!chip->rxd)
+		panic("ftmac110: out of memory 4\n");
+	memset((void *)chip->rxd, 0,
+	       sizeof(struct ftmac110_rxd) * CFG_RXDES_NUM);
+	for (i = 0; i < CFG_RXDES_NUM; ++i) {
+		void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE + 2);
+		if (!va)
+			panic("ftmac110: out of memory 5\n");
+		/* it needs to be exactly 2 bytes aligned */
+		va = ((uint8_t *)va + 2);
+		chip->rxd[i].vbuf  = va;
+		chip->rxd[i].buf   = cpu_to_le32(virt_to_phys(va));
+		chip->rxd[i].ct[1] = cpu_to_le32(CFG_XBUF_SIZE);
+		chip->rxd[i].ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER);
+	}
+	chip->rxd[i - 1].ct[1] |= cpu_to_le32(FTMAC110_RXCT1_END);
+	chip->rxd_idx = 0;
+
+	eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+	miiphy_register(dev->name, ftmac110_mdio_read, ftmac110_mdio_write);
+#endif
+
+	card_nr++;
+
+	return card_nr;
+}
diff --git a/drivers/net/ftmac110.h b/drivers/net/ftmac110.h
new file mode 100644
index 0000000..5b2d23b
--- /dev/null
+++ b/drivers/net/ftmac110.h
@@ -0,0 +1,177 @@
+/*
+ * Faraday 10/100Mbps Ethernet Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ */
+
+#ifndef _FTMAC110_H
+#define _FTMAC110_H
+
+struct ftmac110_regs {
+	uint32_t isr;    /* 0x00: Interrups Status Register */
+	uint32_t imr;    /* 0x04: Interrupt Mask Register */
+	uint32_t mac[2]; /* 0x08: MAC Address */
+	uint32_t mht[2]; /* 0x10: Multicast Hash Table Register */
+	uint32_t txpd;   /* 0x18: Tx Poll Demand Register */
+	uint32_t rxpd;   /* 0x1c: Rx Poll Demand Register */
+	uint32_t txba;   /* 0x20: Tx Ring Base Address Register */
+	uint32_t rxba;   /* 0x24: Rx Ring Base Address Register */
+	uint32_t itc;    /* 0x28: Interrupt Timer Control Register */
+	uint32_t aptc;   /* 0x2C: Automatic Polling Timer Control Register */
+	uint32_t dblac;  /* 0x30: DMA Burst Length&Arbitration Control */
+	uint32_t revr;   /* 0x34: Revision Register */
+	uint32_t fear;   /* 0x38: Feature Register */
+	uint32_t rsvd[19];
+	uint32_t maccr;  /* 0x88: MAC Control Register */
+	uint32_t macsr;  /* 0x8C: MAC Status Register */
+	uint32_t phycr;  /* 0x90: PHY Control Register */
+	uint32_t phydr;  /* 0x94: PHY Data Register */
+	uint32_t fcr;    /* 0x98: Flow Control Register */
+	uint32_t bpr;    /* 0x9C: Back Pressure Register */
+};
+
+/*
+ * Interrupt status/mask register(ISR/IMR) bits
+ */
+#define ISR_ALL          0x3ff
+#define ISR_PHYSTCHG     (1 << 9) /* phy status change */
+#define ISR_AHBERR       (1 << 8) /* bus error */
+#define ISR_RXLOST       (1 << 7) /* rx lost */
+#define ISR_RXFIFO       (1 << 6) /* rx to fifo */
+#define ISR_TXLOST       (1 << 5) /* tx lost */
+#define ISR_TXOK         (1 << 4) /* tx to ethernet */
+#define ISR_NOTXBUF      (1 << 3) /* out of tx buffer */
+#define ISR_TXFIFO       (1 << 2) /* tx to fifo */
+#define ISR_NORXBUF      (1 << 1) /* out of rx buffer */
+#define ISR_RXOK         (1 << 0) /* rx to buffer */
+
+/*
+ * MACCR control bits
+ */
+#define MACCR_100M       (1 << 18) /* 100Mbps mode */
+#define MACCR_RXBCST     (1 << 17) /* rx broadcast packet */
+#define MACCR_RXMCST     (1 << 16) /* rx multicast packet */
+#define MACCR_FD         (1 << 15) /* full duplex */
+#define MACCR_CRCAPD     (1 << 14) /* tx crc append */
+#define MACCR_RXALL      (1 << 12) /* rx all packets */
+#define MACCR_RXFTL      (1 << 11) /* rx packet even it's > 1518 byte */
+#define MACCR_RXRUNT     (1 << 10) /* rx packet even it's < 64 byte */
+#define MACCR_RXMCSTHT   (1 << 9)  /* rx multicast hash table */
+#define MACCR_RXEN       (1 << 8)  /* rx enable */
+#define MACCR_RXINHDTX   (1 << 6)  /* rx in half duplex tx */
+#define MACCR_TXEN       (1 << 5)  /* tx enable */
+#define MACCR_CRCDIS     (1 << 4)  /* tx packet even it's crc error */
+#define MACCR_LOOPBACK   (1 << 3)  /* loop-back */
+#define MACCR_RESET      (1 << 2)  /* reset */
+#define MACCR_RXDMAEN    (1 << 1)  /* rx dma enable */
+#define MACCR_TXDMAEN    (1 << 0)  /* tx dma enable */
+
+/*
+ * PHYCR control bits
+ */
+#define PHYCR_READ       (1 << 26)
+#define PHYCR_WRITE      (1 << 27)
+#define PHYCR_REG_SHIFT  21
+#define PHYCR_ADDR_SHIFT 16
+
+/*
+ * ITC control bits
+ */
+
+/* Tx Cycle Length */
+#define ITC_TX_CYCLONG   (1 << 15) /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define ITC_TX_CYCNORM   (0 << 15) /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Tx Threshold: Aggregate n interrupts as 1 interrupt */
+#define ITC_TX_THR(n)    (((n) & 0x7) << 12)
+/* Tx Interrupt Timeout = n * Tx Cycle */
+#define ITC_TX_ITMO(n)   (((n) & 0xf) << 8)
+/* Rx Cycle Length */
+#define ITC_RX_CYCLONG   (1 << 7)  /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define ITC_RX_CYCNORM   (0 << 7)  /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Rx Threshold: Aggregate n interrupts as 1 interrupt */
+#define ITC_RX_THR(n)    (((n) & 0x7) << 4)
+/* Rx Interrupt Timeout = n * Rx Cycle */
+#define ITC_RX_ITMO(n)   (((n) & 0xf) << 0)
+
+#define ITC_DEFAULT \
+	(ITC_TX_THR(1) | ITC_TX_ITMO(0) | ITC_RX_THR(1) | ITC_RX_ITMO(0))
+
+/*
+ * APTC contrl bits
+ */
+
+/* Tx Cycle Length */
+#define APTC_TX_CYCLONG  (1 << 12) /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define APTC_TX_CYCNORM  (0 << 12) /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Tx Poll Timeout = n * Tx Cycle, 0=No auto polling */
+#define APTC_TX_PTMO(n)  (((n) & 0xf) << 8)
+/* Rx Cycle Length */
+#define APTC_RX_CYCLONG  (1 << 4)  /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define APTC_RX_CYCNORM  (0 << 4)  /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Rx Poll Timeout = n * Rx Cycle, 0=No auto polling */
+#define APTC_RX_PTMO(n)  (((n) & 0xf) << 0)
+
+#define APTC_DEFAULT     (APTC_TX_PTMO(0) | APTC_RX_PTMO(1))
+
+/*
+ * DBLAC contrl bits
+ */
+#define DBLAC_BURST_MAX_ANY  (0 << 14) /* un-limited */
+#define DBLAC_BURST_MAX_32X4 (2 << 14) /* max = 32 x 4 bytes */
+#define DBLAC_BURST_MAX_64X4 (3 << 14) /* max = 64 x 4 bytes */
+#define DBLAC_RXTHR_EN       (1 << 9)  /* enable rx threshold arbitration */
+#define DBLAC_RXTHR_HIGH(n)  (((n) & 0x7) << 6) /* upper bound = n/8 fifo */
+#define DBLAC_RXTHR_LOW(n)   (((n) & 0x7) << 3) /* lower bound = n/8 fifo */
+#define DBLAC_BURST_CAP16    (1 << 2)  /* support burst 16 */
+#define DBLAC_BURST_CAP8     (1 << 1)  /* support burst 8 */
+#define DBLAC_BURST_CAP4     (1 << 0)  /* support burst 4 */
+
+#define DBLAC_DEFAULT \
+	(DBLAC_RXTHR_EN | DBLAC_RXTHR_HIGH(6) | DBLAC_RXTHR_LOW(2))
+
+/*
+ * descriptor structure
+ */
+struct ftmac110_rxd {
+	uint32_t ct[2];
+	uint32_t buf;
+	void    *vbuf; /* reserved */
+};
+
+#define FTMAC110_RXCT0_OWNER       BIT_MASK(31) /* owner: 1=HW, 0=SW */
+#define FTMAC110_RXCT0_FRS         BIT_MASK(29) /* first pkt desc */
+#define FTMAC110_RXCT0_LRS         BIT_MASK(28) /* last pkt desc */
+#define FTMAC110_RXCT0_ODDNB       BIT_MASK(22) /* odd nibble */
+#define FTMAC110_RXCT0_RUNT        BIT_MASK(21) /* runt pkt */
+#define FTMAC110_RXCT0_FTL         BIT_MASK(20) /* frame too long */
+#define FTMAC110_RXCT0_CRC         BIT_MASK(19) /* pkt crc error */
+#define FTMAC110_RXCT0_ERR         BIT_MASK(18) /* bus error */
+#define FTMAC110_RXCT0_ERRMASK     (0x1f << 18) /* all errors */
+#define FTMAC110_RXCT0_BCST        BIT_MASK(17) /* Bcst pkt */
+#define FTMAC110_RXCT0_MCST        BIT_MASK(16) /* Mcst pkt */
+#define FTMAC110_RXCT0_LEN(x)      ((x) & 0x7ff)
+
+#define FTMAC110_RXCT1_END         BIT_MASK(31)
+#define FTMAC110_RXCT1_BUFSZ(x)    ((x) & 0x7ff)
+
+struct ftmac110_txd {
+	uint32_t ct[2];
+	uint32_t buf;
+	void    *vbuf; /* reserved */
+};
+
+#define FTMAC110_TXCT0_OWNER       BIT_MASK(31) /* owner: 1=HW, 0=SW */
+#define FTMAC110_TXCT0_COL         0x00000003   /* collision */
+
+#define FTMAC110_TXCT1_END         BIT_MASK(31) /* end of ring */
+#define FTMAC110_TXCT1_TXIC        BIT_MASK(30) /* tx done interrupt */
+#define FTMAC110_TXCT1_TX2FIC      BIT_MASK(29) /* tx fifo interrupt */
+#define FTMAC110_TXCT1_FTS         BIT_MASK(28) /* first pkt desc */
+#define FTMAC110_TXCT1_LTS         BIT_MASK(27) /* last pkt desc */
+#define FTMAC110_TXCT1_LEN(x)      ((x) & 0x7ff)
+
+#endif  /* FTMAC110_H */
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
new file mode 100644
index 0000000..b02d59a
--- /dev/null
+++ b/drivers/net/ks8851_mll.c
@@ -0,0 +1,645 @@
+/*
+ * Micrel KS8851_MLL 16bit Network driver
+ * Copyright (c) 2011 Roberto Cerati <roberto.cerati@bticino.it>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+
+#include "ks8851_mll.h"
+
+#define DRIVERNAME			"ks8851_mll"
+
+#define MAX_RECV_FRAMES			32
+#define MAX_BUF_SIZE			2048
+#define TX_BUF_SIZE			2000
+#define RX_BUF_SIZE			2000
+
+static const struct chip_id chip_ids[] =  {
+	{CIDER_ID, "KSZ8851"},
+	{0, NULL},
+};
+
+/*
+ * union ks_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks_tx_hdr {
+	u8      txb[4];
+	__le16  txw[2];
+};
+
+/*
+ * struct ks_net - KS8851 driver private data
+ * @net_device	: The network device we're bound to
+ * @txh		: temporaly buffer to save status/length.
+ * @frame_head_info	: frame header information for multi-pkt rx.
+ * @statelock	: Lock on this structure for tx list.
+ * @msg_enable	: The message flags controlling driver output (see ethtool).
+ * @frame_cnt	: number of frames received.
+ * @bus_width	: i/o bus width.
+ * @irq		: irq number assigned to this device.
+ * @rc_rxqcr	: Cached copy of KS_RXQCR.
+ * @rc_txcr	: Cached copy of KS_TXCR.
+ * @rc_ier	: Cached copy of KS_IER.
+ * @sharedbus	: Multipex(addr and data bus) mode indicator.
+ * @cmd_reg_cache	: command register cached.
+ * @cmd_reg_cache_int	: command register cached. Used in the irq handler.
+ * @promiscuous	: promiscuous mode indicator.
+ * @all_mcast	: mutlicast indicator.
+ * @mcast_lst_size	: size of multicast list.
+ * @mcast_lst		: multicast list.
+ * @mcast_bits		: multicast enabed.
+ * @mac_addr		: MAC address assigned to this device.
+ * @fid			: frame id.
+ * @extra_byte		: number of extra byte prepended rx pkt.
+ * @enabled		: indicator this device works.
+ */
+
+/* Receive multiplex framer header info */
+struct type_frame_head {
+	u16	sts;         /* Frame status */
+	u16	len;         /* Byte count */
+} fr_h_i[MAX_RECV_FRAMES];
+
+struct ks_net {
+	struct net_device	*netdev;
+	union ks_tx_hdr		txh;
+	struct type_frame_head	*frame_head_info;
+	u32			msg_enable;
+	u32			frame_cnt;
+	int			bus_width;
+	int			irq;
+	u16			rc_rxqcr;
+	u16			rc_txcr;
+	u16			rc_ier;
+	u16			sharedbus;
+	u16			cmd_reg_cache;
+	u16			cmd_reg_cache_int;
+	u16			promiscuous;
+	u16			all_mcast;
+	u16			mcast_lst_size;
+	u8			mcast_lst[MAX_MCAST_LST][MAC_ADDR_LEN];
+	u8			mcast_bits[HW_MCAST_SIZE];
+	u8			mac_addr[6];
+	u8                      fid;
+	u8			extra_byte;
+	u8			enabled;
+} ks_str, *ks;
+
+#define BE3             0x8000      /* Byte Enable 3 */
+#define BE2             0x4000      /* Byte Enable 2 */
+#define BE1             0x2000      /* Byte Enable 1 */
+#define BE0             0x1000      /* Byte Enable 0 */
+
+static u8 ks_rdreg8(struct eth_device *dev, u16 offset)
+{
+	u8 shift_bit = offset & 0x03;
+	u8 shift_data = (offset & 1) << 3;
+
+	writew(offset | (BE0 << shift_bit), dev->iobase + 2);
+
+	return (u8)(readw(dev->iobase) >> shift_data);
+}
+
+static u16 ks_rdreg16(struct eth_device *dev, u16 offset)
+{
+	writew(offset | ((BE1 | BE0) << (offset & 0x02)), dev->iobase + 2);
+
+	return readw(dev->iobase);
+}
+
+static void ks_wrreg8(struct eth_device *dev, u16 offset, u8 val)
+{
+	u8 shift_bit = (offset & 0x03);
+	u16 value_write = (u16)(val << ((offset & 1) << 3));
+
+	writew(offset | (BE0 << shift_bit), dev->iobase + 2);
+	writew(value_write, dev->iobase);
+}
+
+static void ks_wrreg16(struct eth_device *dev, u16 offset, u16 val)
+{
+	writew(offset | ((BE1 | BE0) << (offset & 0x02)), dev->iobase + 2);
+	writew(val, dev->iobase);
+}
+
+/*
+ * ks_inblk - read a block of data from QMU. This is called after sudo DMA mode
+ * enabled.
+ * @ks: The chip state
+ * @wptr: buffer address to save data
+ * @len: length in byte to read
+ */
+static inline void ks_inblk(struct eth_device *dev, u16 *wptr, u32 len)
+{
+	len >>= 1;
+
+	while (len--)
+		*wptr++ = readw(dev->iobase);
+}
+
+/*
+ * ks_outblk - write data to QMU. This is called after sudo DMA mode enabled.
+ * @ks: The chip information
+ * @wptr: buffer address
+ * @len: length in byte to write
+ */
+static inline void ks_outblk(struct eth_device *dev, u16 *wptr, u32 len)
+{
+	len >>= 1;
+
+	while (len--)
+		writew(*wptr++, dev->iobase);
+}
+
+static void ks_enable_int(struct eth_device *dev)
+{
+	ks_wrreg16(dev, KS_IER, ks->rc_ier);
+}
+
+static void ks_set_powermode(struct eth_device *dev, unsigned pwrmode)
+{
+	unsigned pmecr;
+
+	ks_rdreg16(dev, KS_GRR);
+	pmecr = ks_rdreg16(dev, KS_PMECR);
+	pmecr &= ~PMECR_PM_MASK;
+	pmecr |= pwrmode;
+
+	ks_wrreg16(dev, KS_PMECR, pmecr);
+}
+
+/*
+ * ks_read_config - read chip configuration of bus width.
+ * @ks: The chip information
+ */
+static void ks_read_config(struct eth_device *dev)
+{
+	u16 reg_data = 0;
+
+	/* Regardless of bus width, 8 bit read should always work. */
+	reg_data = ks_rdreg8(dev, KS_CCR) & 0x00FF;
+	reg_data |= ks_rdreg8(dev, KS_CCR + 1) << 8;
+
+	/* addr/data bus are multiplexed */
+	ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED;
+
+	/*
+	 * There are garbage data when reading data from QMU,
+	 * depending on bus-width.
+	 */
+	if (reg_data & CCR_8BIT) {
+		ks->bus_width = ENUM_BUS_8BIT;
+		ks->extra_byte = 1;
+	} else if (reg_data & CCR_16BIT) {
+		ks->bus_width = ENUM_BUS_16BIT;
+		ks->extra_byte = 2;
+	} else {
+		ks->bus_width = ENUM_BUS_32BIT;
+		ks->extra_byte = 4;
+	}
+}
+
+/*
+ * ks_soft_reset - issue one of the soft reset to the device
+ * @ks: The device state.
+ * @op: The bit(s) to set in the GRR
+ *
+ * Issue the relevant soft-reset command to the device's GRR register
+ * specified by @op.
+ *
+ * Note, the delays are in there as a caution to ensure that the reset
+ * has time to take effect and then complete. Since the datasheet does
+ * not currently specify the exact sequence, we have chosen something
+ * that seems to work with our device.
+ */
+static void ks_soft_reset(struct eth_device *dev, unsigned op)
+{
+	/* Disable interrupt first */
+	ks_wrreg16(dev, KS_IER, 0x0000);
+	ks_wrreg16(dev, KS_GRR, op);
+	mdelay(10);	/* wait a short time to effect reset */
+	ks_wrreg16(dev, KS_GRR, 0);
+	mdelay(1);	/* wait for condition to clear */
+}
+
+void ks_enable_qmu(struct eth_device *dev)
+{
+	u16 w;
+
+	w = ks_rdreg16(dev, KS_TXCR);
+
+	/* Enables QMU Transmit (TXCR). */
+	ks_wrreg16(dev, KS_TXCR, w | TXCR_TXE);
+
+	/* Enable RX Frame Count Threshold and Auto-Dequeue RXQ Frame */
+	w = ks_rdreg16(dev, KS_RXQCR);
+	ks_wrreg16(dev, KS_RXQCR, w | RXQCR_RXFCTE);
+
+	/* Enables QMU Receive (RXCR1). */
+	w = ks_rdreg16(dev, KS_RXCR1);
+	ks_wrreg16(dev, KS_RXCR1, w | RXCR1_RXE);
+}
+
+static void ks_disable_qmu(struct eth_device *dev)
+{
+	u16 w;
+
+	w = ks_rdreg16(dev, KS_TXCR);
+
+	/* Disables QMU Transmit (TXCR). */
+	w &= ~TXCR_TXE;
+	ks_wrreg16(dev, KS_TXCR, w);
+
+	/* Disables QMU Receive (RXCR1). */
+	w = ks_rdreg16(dev, KS_RXCR1);
+	w &= ~RXCR1_RXE;
+	ks_wrreg16(dev, KS_RXCR1, w);
+}
+
+static inline void ks_read_qmu(struct eth_device *dev, u16 *buf, u32 len)
+{
+	u32 r = ks->extra_byte & 0x1;
+	u32 w = ks->extra_byte - r;
+
+	/* 1. set sudo DMA mode */
+	ks_wrreg16(dev, KS_RXFDPR, RXFDPR_RXFPAI);
+	ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+
+	/*
+	 * 2. read prepend data
+	 *
+	 * read 4 + extra bytes and discard them.
+	 * extra bytes for dummy, 2 for status, 2 for len
+	 */
+
+	if (r)
+		ks_rdreg8(dev, 0);
+
+	ks_inblk(dev, buf, w + 2 + 2);
+
+	/* 3. read pkt data */
+	ks_inblk(dev, buf, ALIGN(len, 4));
+
+	/* 4. reset sudo DMA Mode */
+	ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr & ~RXQCR_SDA) & 0xff);
+}
+
+static void ks_rcv(struct eth_device *dev, uchar **pv_data)
+{
+	struct type_frame_head *frame_hdr = ks->frame_head_info;
+	int i;
+
+	ks->frame_cnt = ks_rdreg16(dev, KS_RXFCTR) >> 8;
+
+	/* read all header information */
+	for (i = 0; i < ks->frame_cnt; i++) {
+		/* Checking Received packet status */
+		frame_hdr->sts = ks_rdreg16(dev, KS_RXFHSR);
+		/* Get packet len from hardware */
+		frame_hdr->len = ks_rdreg16(dev, KS_RXFHBCR);
+		frame_hdr++;
+	}
+
+	frame_hdr = ks->frame_head_info;
+	while (ks->frame_cnt--) {
+		if ((frame_hdr->sts & RXFSHR_RXFV) &&
+		    (frame_hdr->len < RX_BUF_SIZE) &&
+		    frame_hdr->len) {
+			/* read data block including CRC 4 bytes */
+			ks_read_qmu(dev, (u16 *)(*pv_data), frame_hdr->len);
+
+			/* NetRxPackets buffer size is ok (*pv_data pointer) */
+			NetReceive(*pv_data, frame_hdr->len);
+			pv_data++;
+		} else {
+			ks_wrreg16(dev, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF));
+			printf(DRIVERNAME ": bad packet\n");
+		}
+		frame_hdr++;
+	}
+}
+
+/*
+ * ks_read_selftest - read the selftest memory info.
+ * @ks: The device state
+ *
+ * Read and check the TX/RX memory selftest information.
+ */
+static int ks_read_selftest(struct eth_device *dev)
+{
+	u16 both_done = MBIR_TXMBF | MBIR_RXMBF;
+	u16 mbir;
+	int ret = 0;
+
+	mbir = ks_rdreg16(dev, KS_MBIR);
+
+	if ((mbir & both_done) != both_done) {
+		printf(DRIVERNAME ": Memory selftest not finished\n");
+		return 0;
+	}
+
+	if (mbir & MBIR_TXMBFA) {
+		printf(DRIVERNAME ": TX memory selftest fails\n");
+		ret |= 1;
+	}
+
+	if (mbir & MBIR_RXMBFA) {
+		printf(DRIVERNAME ": RX memory selftest fails\n");
+		ret |= 2;
+	}
+
+	debug(DRIVERNAME ": the selftest passes\n");
+
+	return ret;
+}
+
+static void ks_setup(struct eth_device *dev)
+{
+	u16 w;
+
+	/* Setup Transmit Frame Data Pointer Auto-Increment (TXFDPR) */
+	ks_wrreg16(dev, KS_TXFDPR, TXFDPR_TXFPAI);
+
+	/* Setup Receive Frame Data Pointer Auto-Increment */
+	ks_wrreg16(dev, KS_RXFDPR, RXFDPR_RXFPAI);
+
+	/* Setup Receive Frame Threshold - 1 frame (RXFCTFC) */
+	ks_wrreg16(dev, KS_RXFCTR, 1 & RXFCTR_THRESHOLD_MASK);
+
+	/* Setup RxQ Command Control (RXQCR) */
+	ks->rc_rxqcr = RXQCR_CMD_CNTL;
+	ks_wrreg16(dev, KS_RXQCR, ks->rc_rxqcr);
+
+	/*
+	 * set the force mode to half duplex, default is full duplex
+	 * because if the auto-negotiation fails, most switch uses
+	 * half-duplex.
+	 */
+	w = ks_rdreg16(dev, KS_P1MBCR);
+	w &= ~P1MBCR_FORCE_FDX;
+	ks_wrreg16(dev, KS_P1MBCR, w);
+
+	w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP;
+	ks_wrreg16(dev, KS_TXCR, w);
+
+	w = RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXUE | RXCR1_RXME | RXCR1_RXIPFCC;
+
+	/* Normal mode */
+	w |= RXCR1_RXPAFMA;
+
+	ks_wrreg16(dev, KS_RXCR1, w);
+}
+
+static void ks_setup_int(struct eth_device *dev)
+{
+	ks->rc_ier = 0x00;
+
+	/* Clear the interrupts status of the hardware. */
+	ks_wrreg16(dev, KS_ISR, 0xffff);
+
+	/* Enables the interrupts of the hardware. */
+	ks->rc_ier = (IRQ_LCI | IRQ_TXI | IRQ_RXI);
+}
+
+static int ks8851_mll_detect_chip(struct eth_device *dev)
+{
+	unsigned short val, i;
+
+	ks_read_config(dev);
+
+	val = ks_rdreg16(dev, KS_CIDER);
+
+	if (val == 0xffff) {
+		/* Special case -- no chip present */
+		printf(DRIVERNAME ":  is chip mounted ?\n");
+		return -1;
+	} else if ((val & 0xfff0) != CIDER_ID) {
+		printf(DRIVERNAME ": Invalid chip id 0x%04x\n", val);
+		return -1;
+	}
+
+	debug("Read back KS8851 id 0x%x\n", val);
+
+	/* only one entry in the table */
+	val &= 0xfff0;
+	for (i = 0; chip_ids[i].id != 0; i++) {
+		if (chip_ids[i].id == val)
+			break;
+	}
+	if (!chip_ids[i].id) {
+		printf(DRIVERNAME ": Unknown chip ID %04x\n", val);
+		return -1;
+	}
+
+	dev->priv = (void *)&chip_ids[i];
+
+	return 0;
+}
+
+static void ks8851_mll_reset(struct eth_device *dev)
+{
+	/* wake up powermode to normal mode */
+	ks_set_powermode(dev, PMECR_PM_NORMAL);
+	mdelay(1);	/* wait for normal mode to take effect */
+
+	/* Disable interrupt and reset */
+	ks_soft_reset(dev, GRR_GSR);
+
+	/* turn off the IRQs and ack any outstanding */
+	ks_wrreg16(dev, KS_IER, 0x0000);
+	ks_wrreg16(dev, KS_ISR, 0xffff);
+
+	/* shutdown RX/TX QMU */
+	ks_disable_qmu(dev);
+}
+
+static void ks8851_mll_phy_configure(struct eth_device *dev)
+{
+	u16 data;
+
+	ks_setup(dev);
+	ks_setup_int(dev);
+
+	/* Probing the phy */
+	data = ks_rdreg16(dev, KS_OBCR);
+	ks_wrreg16(dev, KS_OBCR, data | OBCR_ODS_16MA);
+
+	debug(DRIVERNAME ": phy initialized\n");
+}
+
+static void ks8851_mll_enable(struct eth_device *dev)
+{
+	ks_wrreg16(dev, KS_ISR, 0xffff);
+	ks_enable_int(dev);
+	ks_enable_qmu(dev);
+}
+
+static int ks8851_mll_init(struct eth_device *dev, bd_t *bd)
+{
+	struct chip_id *id = dev->priv;
+
+	debug(DRIVERNAME ": detected %s controller\n", id->name);
+
+	if (ks_read_selftest(dev)) {
+		printf(DRIVERNAME ": Selftest failed\n");
+		return -1;
+	}
+
+	ks8851_mll_reset(dev);
+
+	/* Configure the PHY, initialize the link state */
+	ks8851_mll_phy_configure(dev);
+
+	/* static allocation of private informations */
+	ks->frame_head_info = fr_h_i;
+
+	/* Turn on Tx + Rx */
+	ks8851_mll_enable(dev);
+
+	return 0;
+}
+
+static void ks_write_qmu(struct eth_device *dev, u8 *pdata, u16 len)
+{
+	/* start header at txb[0] to align txw entries */
+	ks->txh.txw[0] = 0;
+	ks->txh.txw[1] = cpu_to_le16(len);
+
+	/* 1. set sudo-DMA mode */
+	ks_wrreg16(dev, KS_TXFDPR, TXFDPR_TXFPAI);
+	ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+	/* 2. write status/lenth info */
+	ks_outblk(dev, ks->txh.txw, 4);
+	/* 3. write pkt data */
+	ks_outblk(dev, (u16 *)pdata, ALIGN(len, 4));
+	/* 4. reset sudo-DMA mode */
+	ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr & ~RXQCR_SDA) & 0xff);
+	/* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */
+	ks_wrreg16(dev, KS_TXQCR, TXQCR_METFE);
+	/* 6. wait until TXQCR_METFE is auto-cleared */
+	do { } while (ks_rdreg16(dev, KS_TXQCR) & TXQCR_METFE);
+}
+
+static int ks8851_mll_send(struct eth_device *dev, void *packet, int length)
+{
+	u8 *data = (u8 *)packet;
+	u16 tmplen = (u16)length;
+	u16 retv;
+
+	/*
+	 * Extra space are required:
+	 * 4 byte for alignment, 4 for status/length, 4 for CRC
+	 */
+	retv = ks_rdreg16(dev, KS_TXMIR) & 0x1fff;
+	if (retv >= tmplen + 12) {
+		ks_write_qmu(dev, data, tmplen);
+		return 0;
+	} else {
+		printf(DRIVERNAME ": failed to send packet: No buffer\n");
+		return -1;
+	}
+}
+
+static void ks8851_mll_halt(struct eth_device *dev)
+{
+	ks8851_mll_reset(dev);
+}
+
+/*
+ * Maximum receive ring size; that is, the number of packets
+ * we can buffer before overflow happens. Basically, this just
+ * needs to be enough to prevent a packet being discarded while
+ * we are processing the previous one.
+ */
+static int ks8851_mll_recv(struct eth_device *dev)
+{
+	u16 status;
+
+	status = ks_rdreg16(dev, KS_ISR);
+
+	ks_wrreg16(dev, KS_ISR, status);
+
+	if ((status & IRQ_RXI))
+		ks_rcv(dev, (uchar **)NetRxPackets);
+
+	if ((status & IRQ_LDI)) {
+		u16 pmecr = ks_rdreg16(dev, KS_PMECR);
+		pmecr &= ~PMECR_WKEVT_MASK;
+		ks_wrreg16(dev, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+	}
+
+	return 0;
+}
+
+static int ks8851_mll_write_hwaddr(struct eth_device *dev)
+{
+	u16 addrl, addrm, addrh;
+
+	addrh = (dev->enetaddr[0] << 8) | dev->enetaddr[1];
+	addrm = (dev->enetaddr[2] << 8) | dev->enetaddr[3];
+	addrl = (dev->enetaddr[4] << 8) | dev->enetaddr[5];
+
+	ks_wrreg16(dev, KS_MARH, addrh);
+	ks_wrreg16(dev, KS_MARM, addrm);
+	ks_wrreg16(dev, KS_MARL, addrl);
+
+	return 0;
+}
+
+int ks8851_mll_initialize(u8 dev_num, int base_addr)
+{
+	struct eth_device *dev;
+
+	dev = malloc(sizeof(*dev));
+	if (!dev) {
+		printf("Error: Failed to allocate memory\n");
+		return -1;
+	}
+	memset(dev, 0, sizeof(*dev));
+
+	dev->iobase = base_addr;
+
+	ks = &ks_str;
+
+	/* Try to detect chip. Will fail if not present. */
+	if (ks8851_mll_detect_chip(dev)) {
+		free(dev);
+		return -1;
+	}
+
+	dev->init = ks8851_mll_init;
+	dev->halt = ks8851_mll_halt;
+	dev->send = ks8851_mll_send;
+	dev->recv = ks8851_mll_recv;
+	dev->write_hwaddr = ks8851_mll_write_hwaddr;
+	sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num);
+
+	eth_register(dev);
+
+	return 0;
+}
diff --git a/drivers/net/ks8851_mll.h b/drivers/net/ks8851_mll.h
new file mode 100644
index 0000000..7f90ae4
--- /dev/null
+++ b/drivers/net/ks8851_mll.h
@@ -0,0 +1,357 @@
+/*
+ * drivers/net/ks8851_mll.c
+ *
+ * Supports:
+ * KS8851 16bit MLL chip from Micrel Inc.
+ *
+ * Copyright (c) 2009 Micrel Inc.
+ *
+ * modified by
+ * (c) 2011 Bticino s.p.a, Roberto Cerati <roberto.cerati@bticino.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _KS8851_MLL_H_
+#define _KS8851_MLL_H_
+
+#include <linux/types.h>
+
+#define KS_CCR				0x08
+#define CCR_EEPROM			(1 << 9)
+#define CCR_SPI				(1 << 8)
+#define CCR_8BIT			(1 << 7)
+#define CCR_16BIT			(1 << 6)
+#define CCR_32BIT			(1 << 5)
+#define CCR_SHARED			(1 << 4)
+#define CCR_32PIN			(1 << 0)
+
+/* MAC address registers */
+#define KS_MARL				0x10
+#define KS_MARM				0x12
+#define KS_MARH				0x14
+
+#define KS_OBCR				0x20
+#define OBCR_ODS_16MA			(1 << 6)
+
+#define KS_EEPCR			0x22
+#define EEPCR_EESA			(1 << 4)
+#define EEPCR_EESB			(1 << 3)
+#define EEPCR_EEDO			(1 << 2)
+#define EEPCR_EESCK			(1 << 1)
+#define EEPCR_EECS			(1 << 0)
+
+#define KS_MBIR				0x24
+#define MBIR_TXMBF			(1 << 12)
+#define MBIR_TXMBFA			(1 << 11)
+#define MBIR_RXMBF			(1 << 4)
+#define MBIR_RXMBFA			(1 << 3)
+
+#define KS_GRR				0x26
+#define GRR_QMU				(1 << 1)
+#define GRR_GSR				(1 << 0)
+
+#define KS_WFCR				0x2A
+#define WFCR_MPRXE			(1 << 7)
+#define WFCR_WF3E			(1 << 3)
+#define WFCR_WF2E			(1 << 2)
+#define WFCR_WF1E			(1 << 1)
+#define WFCR_WF0E			(1 << 0)
+
+#define KS_WF0CRC0			0x30
+#define KS_WF0CRC1			0x32
+#define KS_WF0BM0			0x34
+#define KS_WF0BM1			0x36
+#define KS_WF0BM2			0x38
+#define KS_WF0BM3			0x3A
+
+#define KS_WF1CRC0			0x40
+#define KS_WF1CRC1			0x42
+#define KS_WF1BM0			0x44
+#define KS_WF1BM1			0x46
+#define KS_WF1BM2			0x48
+#define KS_WF1BM3			0x4A
+
+#define KS_WF2CRC0			0x50
+#define KS_WF2CRC1			0x52
+#define KS_WF2BM0			0x54
+#define KS_WF2BM1			0x56
+#define KS_WF2BM2			0x58
+#define KS_WF2BM3			0x5A
+
+#define KS_WF3CRC0			0x60
+#define KS_WF3CRC1			0x62
+#define KS_WF3BM0			0x64
+#define KS_WF3BM1			0x66
+#define KS_WF3BM2			0x68
+#define KS_WF3BM3			0x6A
+
+#define KS_TXCR				0x70
+#define TXCR_TCGICMP			(1 << 8)
+#define TXCR_TCGUDP			(1 << 7)
+#define TXCR_TCGTCP			(1 << 6)
+#define TXCR_TCGIP			(1 << 5)
+#define TXCR_FTXQ			(1 << 4)
+#define TXCR_TXFCE			(1 << 3)
+#define TXCR_TXPE			(1 << 2)
+#define TXCR_TXCRC			(1 << 1)
+#define TXCR_TXE			(1 << 0)
+
+#define KS_TXSR				0x72
+#define TXSR_TXLC			(1 << 13)
+#define TXSR_TXMC			(1 << 12)
+#define TXSR_TXFID_MASK			(0x3f << 0)
+#define TXSR_TXFID_SHIFT		(0)
+#define TXSR_TXFID_GET(_v)		(((_v) >> 0) & 0x3f)
+
+
+#define KS_RXCR1			0x74
+#define RXCR1_FRXQ			(1 << 15)
+#define RXCR1_RXUDPFCC			(1 << 14)
+#define RXCR1_RXTCPFCC			(1 << 13)
+#define RXCR1_RXIPFCC			(1 << 12)
+#define RXCR1_RXPAFMA			(1 << 11)
+#define RXCR1_RXFCE			(1 << 10)
+#define RXCR1_RXEFE			(1 << 9)
+#define RXCR1_RXMAFMA			(1 << 8)
+#define RXCR1_RXBE			(1 << 7)
+#define RXCR1_RXME			(1 << 6)
+#define RXCR1_RXUE			(1 << 5)
+#define RXCR1_RXAE			(1 << 4)
+#define RXCR1_RXINVF			(1 << 1)
+#define RXCR1_RXE			(1 << 0)
+#define RXCR1_FILTER_MASK		(RXCR1_RXINVF | RXCR1_RXAE | \
+					 RXCR1_RXMAFMA | RXCR1_RXPAFMA)
+
+#define KS_RXCR2			0x76
+#define RXCR2_SRDBL_MASK		(0x7 << 5)
+#define RXCR2_SRDBL_SHIFT		(5)
+#define RXCR2_SRDBL_4B			(0x0 << 5)
+#define RXCR2_SRDBL_8B			(0x1 << 5)
+#define RXCR2_SRDBL_16B			(0x2 << 5)
+#define RXCR2_SRDBL_32B			(0x3 << 5)
+/* #define RXCR2_SRDBL_FRAME		(0x4 << 5) */
+#define RXCR2_IUFFP			(1 << 4)
+#define RXCR2_RXIUFCEZ			(1 << 3)
+#define RXCR2_UDPLFE			(1 << 2)
+#define RXCR2_RXICMPFCC			(1 << 1)
+#define RXCR2_RXSAF			(1 << 0)
+
+#define KS_TXMIR			0x78
+
+#define KS_RXFHSR			0x7C
+#define RXFSHR_RXFV			(1 << 15)
+#define RXFSHR_RXICMPFCS		(1 << 13)
+#define RXFSHR_RXIPFCS			(1 << 12)
+#define RXFSHR_RXTCPFCS			(1 << 11)
+#define RXFSHR_RXUDPFCS			(1 << 10)
+#define RXFSHR_RXBF			(1 << 7)
+#define RXFSHR_RXMF			(1 << 6)
+#define RXFSHR_RXUF			(1 << 5)
+#define RXFSHR_RXMR			(1 << 4)
+#define RXFSHR_RXFT			(1 << 3)
+#define RXFSHR_RXFTL			(1 << 2)
+#define RXFSHR_RXRF			(1 << 1)
+#define RXFSHR_RXCE			(1 << 0)
+#define RXFSHR_ERR			(RXFSHR_RXCE | RXFSHR_RXRF |\
+					RXFSHR_RXFTL | RXFSHR_RXMR |\
+					RXFSHR_RXICMPFCS | RXFSHR_RXIPFCS |\
+					RXFSHR_RXTCPFCS)
+#define KS_RXFHBCR			0x7E
+#define RXFHBCR_CNT_MASK		0x0FFF
+
+#define KS_TXQCR			0x80
+#define TXQCR_AETFE			(1 << 2)
+#define TXQCR_TXQMAM			(1 << 1)
+#define TXQCR_METFE			(1 << 0)
+
+#define KS_RXQCR			0x82
+#define RXQCR_RXDTTS			(1 << 12)
+#define RXQCR_RXDBCTS			(1 << 11)
+#define RXQCR_RXFCTS			(1 << 10)
+#define RXQCR_RXIPHTOE			(1 << 9)
+#define RXQCR_RXDTTE			(1 << 7)
+#define RXQCR_RXDBCTE			(1 << 6)
+#define RXQCR_RXFCTE			(1 << 5)
+#define RXQCR_ADRFE			(1 << 4)
+#define RXQCR_SDA			(1 << 3)
+#define RXQCR_RRXEF			(1 << 0)
+#define RXQCR_CMD_CNTL			(RXQCR_RXFCTE|RXQCR_ADRFE)
+
+#define KS_TXFDPR			0x84
+#define TXFDPR_TXFPAI			(1 << 14)
+#define TXFDPR_TXFP_MASK		(0x7ff << 0)
+#define TXFDPR_TXFP_SHIFT		(0)
+
+#define KS_RXFDPR			0x86
+#define RXFDPR_RXFPAI			(1 << 14)
+
+#define KS_RXDTTR			0x8C
+#define KS_RXDBCTR			0x8E
+
+#define KS_IER				0x90
+#define KS_ISR				0x92
+#define IRQ_LCI				(1 << 15)
+#define IRQ_TXI				(1 << 14)
+#define IRQ_RXI				(1 << 13)
+#define IRQ_RXOI			(1 << 11)
+#define IRQ_TXPSI			(1 << 9)
+#define IRQ_RXPSI			(1 << 8)
+#define IRQ_TXSAI			(1 << 6)
+#define IRQ_RXWFDI			(1 << 5)
+#define IRQ_RXMPDI			(1 << 4)
+#define IRQ_LDI				(1 << 3)
+#define IRQ_EDI				(1 << 2)
+#define IRQ_SPIBEI			(1 << 1)
+#define IRQ_DEDI			(1 << 0)
+
+#define KS_RXFCTR			0x9C
+#define RXFCTR_THRESHOLD_MASK		0x00FF
+
+#define KS_RXFC				0x9D
+#define RXFCTR_RXFC_MASK		(0xff << 8)
+#define RXFCTR_RXFC_SHIFT		(8)
+#define RXFCTR_RXFC_GET(_v)		(((_v) >> 8) & 0xff)
+#define RXFCTR_RXFCT_MASK		(0xff << 0)
+#define RXFCTR_RXFCT_SHIFT		(0)
+
+#define KS_TXNTFSR			0x9E
+
+#define KS_MAHTR0			0xA0
+#define KS_MAHTR1			0xA2
+#define KS_MAHTR2			0xA4
+#define KS_MAHTR3			0xA6
+
+#define KS_FCLWR			0xB0
+#define KS_FCHWR			0xB2
+#define KS_FCOWR			0xB4
+
+#define KS_CIDER			0xC0
+#define CIDER_ID			0x8870
+#define CIDER_REV_MASK			(0x7 << 1)
+#define CIDER_REV_SHIFT			(1)
+#define CIDER_REV_GET(_v)		(((_v) >> 1) & 0x7)
+
+#define KS_CGCR				0xC6
+#define KS_IACR				0xC8
+#define IACR_RDEN			(1 << 12)
+#define IACR_TSEL_MASK			(0x3 << 10)
+#define IACR_TSEL_SHIFT			(10)
+#define IACR_TSEL_MIB			(0x3 << 10)
+#define IACR_ADDR_MASK			(0x1f << 0)
+#define IACR_ADDR_SHIFT			(0)
+
+#define KS_IADLR			0xD0
+#define KS_IAHDR			0xD2
+
+#define KS_PMECR			0xD4
+#define PMECR_PME_DELAY			(1 << 14)
+#define PMECR_PME_POL			(1 << 12)
+#define PMECR_WOL_WAKEUP		(1 << 11)
+#define PMECR_WOL_MAGICPKT		(1 << 10)
+#define PMECR_WOL_LINKUP		(1 << 9)
+#define PMECR_WOL_ENERGY		(1 << 8)
+#define PMECR_AUTO_WAKE_EN		(1 << 7)
+#define PMECR_WAKEUP_NORMAL		(1 << 6)
+#define PMECR_WKEVT_MASK		(0xf << 2)
+#define PMECR_WKEVT_SHIFT		(2)
+#define PMECR_WKEVT_GET(_v)		(((_v) >> 2) & 0xf)
+#define PMECR_WKEVT_ENERGY		(0x1 << 2)
+#define PMECR_WKEVT_LINK		(0x2 << 2)
+#define PMECR_WKEVT_MAGICPKT		(0x4 << 2)
+#define PMECR_WKEVT_FRAME		(0x8 << 2)
+#define PMECR_PM_MASK			(0x3 << 0)
+#define PMECR_PM_SHIFT			(0)
+#define PMECR_PM_NORMAL			(0x0 << 0)
+#define PMECR_PM_ENERGY			(0x1 << 0)
+#define PMECR_PM_SOFTDOWN		(0x2 << 0)
+#define PMECR_PM_POWERSAVE		(0x3 << 0)
+
+/* Standard MII PHY data */
+#define KS_P1MBCR			0xE4
+#define P1MBCR_FORCE_FDX		(1 << 8)
+
+#define KS_P1MBSR			0xE6
+#define P1MBSR_AN_COMPLETE		(1 << 5)
+#define P1MBSR_AN_CAPABLE		(1 << 3)
+#define P1MBSR_LINK_UP			(1 << 2)
+
+#define KS_PHY1ILR			0xE8
+#define KS_PHY1IHR			0xEA
+#define KS_P1ANAR			0xEC
+#define KS_P1ANLPR			0xEE
+
+#define KS_P1SCLMD			0xF4
+#define P1SCLMD_LEDOFF			(1 << 15)
+#define P1SCLMD_TXIDS			(1 << 14)
+#define P1SCLMD_RESTARTAN		(1 << 13)
+#define P1SCLMD_DISAUTOMDIX		(1 << 10)
+#define P1SCLMD_FORCEMDIX		(1 << 9)
+#define P1SCLMD_AUTONEGEN		(1 << 7)
+#define P1SCLMD_FORCE100		(1 << 6)
+#define P1SCLMD_FORCEFDX		(1 << 5)
+#define P1SCLMD_ADV_FLOW		(1 << 4)
+#define P1SCLMD_ADV_100BT_FDX		(1 << 3)
+#define P1SCLMD_ADV_100BT_HDX		(1 << 2)
+#define P1SCLMD_ADV_10BT_FDX		(1 << 1)
+#define P1SCLMD_ADV_10BT_HDX		(1 << 0)
+
+#define KS_P1CR				0xF6
+#define P1CR_HP_MDIX			(1 << 15)
+#define P1CR_REV_POL			(1 << 13)
+#define P1CR_OP_100M			(1 << 10)
+#define P1CR_OP_FDX			(1 << 9)
+#define P1CR_OP_MDI			(1 << 7)
+#define P1CR_AN_DONE			(1 << 6)
+#define P1CR_LINK_GOOD			(1 << 5)
+#define P1CR_PNTR_FLOW			(1 << 4)
+#define P1CR_PNTR_100BT_FDX		(1 << 3)
+#define P1CR_PNTR_100BT_HDX		(1 << 2)
+#define P1CR_PNTR_10BT_FDX		(1 << 1)
+#define P1CR_PNTR_10BT_HDX		(1 << 0)
+
+/* TX Frame control */
+#define TXFR_TXIC			(1 << 15)
+#define TXFR_TXFID_MASK			(0x3f << 0)
+#define TXFR_TXFID_SHIFT		(0)
+
+#define KS_P1SR				0xF8
+#define P1SR_HP_MDIX			(1 << 15)
+#define P1SR_REV_POL			(1 << 13)
+#define P1SR_OP_100M			(1 << 10)
+#define P1SR_OP_FDX			(1 << 9)
+#define P1SR_OP_MDI			(1 << 7)
+#define P1SR_AN_DONE			(1 << 6)
+#define P1SR_LINK_GOOD			(1 << 5)
+#define P1SR_PNTR_FLOW			(1 << 4)
+#define P1SR_PNTR_100BT_FDX		(1 << 3)
+#define P1SR_PNTR_100BT_HDX		(1 << 2)
+#define P1SR_PNTR_10BT_FDX		(1 << 1)
+#define P1SR_PNTR_10BT_HDX		(1 << 0)
+
+#define ENUM_BUS_NONE			0
+#define ENUM_BUS_8BIT			1
+#define ENUM_BUS_16BIT			2
+#define ENUM_BUS_32BIT			3
+
+#define MAX_MCAST_LST			32
+#define HW_MCAST_SIZE			8
+#define MAC_ADDR_LEN			6
+
+/* Chip ID values */
+struct chip_id {
+	u16 id;
+	char *name;
+};
+
+#endif
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 8bacbda..b7802a2 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -103,9 +103,15 @@
 	const struct device	*dev;
 	struct eth_device	netdev;
 	unsigned short		phy_addr;
+	struct mii_dev		*bus;
 };
 #define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
 
+static int macb_is_gem(struct macb_device *macb)
+{
+	return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2;
+}
+
 static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
 {
 	unsigned long netctl;
@@ -163,7 +169,12 @@
 	return MACB_BFEXT(DATA, frame);
 }
 
-#if defined(CONFIG_CMD_MII)
+void __weak arch_get_mdio_control(const char *name)
+{
+	return;
+}
+
+#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 
 int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
 {
@@ -173,6 +184,7 @@
 	if ( macb->phy_addr != phy_adr )
 		return -1;
 
+	arch_get_mdio_control(devname);
 	*value = macb_mdio_read(macb, reg);
 
 	return 0;
@@ -186,6 +198,7 @@
 	if ( macb->phy_addr != phy_adr )
 		return -1;
 
+	arch_get_mdio_control(devname);
 	macb_mdio_write(macb, reg, value);
 
 	return 0;
@@ -372,11 +385,15 @@
 static int macb_phy_init(struct macb_device *macb)
 {
 	struct eth_device *netdev = &macb->netdev;
+#ifdef CONFIG_PHYLIB
+	struct phy_device *phydev;
+#endif
 	u32 ncfgr;
 	u16 phy_id, status, adv, lpa;
 	int media, speed, duplex;
 	int i;
 
+	arch_get_mdio_control(netdev->name);
 #ifdef CONFIG_MACB_SEARCH_PHY
 	/* Auto-detect phy_addr */
 	if (!macb_phy_find(macb)) {
@@ -391,6 +408,13 @@
 		return 0;
 	}
 
+#ifdef CONFIG_PHYLIB
+	phydev->bus = macb->bus;
+	phydev->dev = netdev;
+	phydev->addr = macb->phy_addr;
+	phy_config(phydev);
+#endif
+
 	status = macb_mdio_read(macb, MII_BMSR);
 	if (!(status & BMSR_LSTATUS)) {
 		/* Try to re-negotiate if we don't have link already. */
@@ -408,28 +432,64 @@
 		printf("%s: link down (status: 0x%04x)\n",
 		       netdev->name, status);
 		return 0;
-	} else {
-		adv = macb_mdio_read(macb, MII_ADVERTISE);
-		lpa = macb_mdio_read(macb, MII_LPA);
-		media = mii_nway_result(lpa & adv);
-		speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
-			 ? 1 : 0);
-		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
-		printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
-		       netdev->name,
-		       speed ? "100" : "10",
-		       duplex ? "full" : "half",
-		       lpa);
-
-		ncfgr = macb_readl(macb, NCFGR);
-		ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
-		if (speed)
-			ncfgr |= MACB_BIT(SPD);
-		if (duplex)
-			ncfgr |= MACB_BIT(FD);
-		macb_writel(macb, NCFGR, ncfgr);
-		return 1;
 	}
+
+	/* First check for GMAC */
+	if (macb_is_gem(macb)) {
+		lpa = macb_mdio_read(macb, MII_STAT1000);
+		if (lpa & (1 << 11)) {
+			speed = 1000;
+			duplex = 1;
+		} else {
+		       if (lpa & (1 << 10)) {
+				speed = 1000;
+				duplex = 1;
+			} else {
+				speed = 0;
+			}
+		}
+
+		if (speed == 1000) {
+			printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n",
+			       netdev->name,
+			       speed,
+			       duplex ? "full" : "half",
+			       lpa);
+
+			ncfgr = macb_readl(macb, NCFGR);
+			ncfgr &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD));
+			if (speed)
+				ncfgr |= GEM_BIT(GBE);
+			if (duplex)
+				ncfgr |= MACB_BIT(FD);
+			macb_writel(macb, NCFGR, ncfgr);
+
+			return 1;
+		}
+	}
+
+	/* fall back for EMAC checking */
+	adv = macb_mdio_read(macb, MII_ADVERTISE);
+	lpa = macb_mdio_read(macb, MII_LPA);
+	media = mii_nway_result(lpa & adv);
+	speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
+		 ? 1 : 0);
+	duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+	printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
+	       netdev->name,
+	       speed ? "100" : "10",
+	       duplex ? "full" : "half",
+	       lpa);
+
+	ncfgr = macb_readl(macb, NCFGR);
+	ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+	if (speed)
+		ncfgr |= MACB_BIT(SPD);
+	if (duplex)
+		ncfgr |= MACB_BIT(FD);
+	macb_writel(macb, NCFGR, ncfgr);
+
+	return 1;
 }
 
 static int macb_init(struct eth_device *netdev, bd_t *bd)
@@ -464,26 +524,28 @@
 	macb_writel(macb, RBQP, macb->rx_ring_dma);
 	macb_writel(macb, TBQP, macb->tx_ring_dma);
 
+	if (macb_is_gem(macb)) {
+#ifdef CONFIG_RGMII
+		gem_writel(macb, UR, GEM_BIT(RGMII));
+#else
+		gem_writel(macb, UR, 0);
+#endif
+	} else {
 	/* choose RMII or MII mode. This depends on the board */
 #ifdef CONFIG_RMII
-#if	defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
-	defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \
-	defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
-	defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5)
+#ifdef CONFIG_AT91FAMILY
 	macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
 #else
 	macb_writel(macb, USRIO, 0);
 #endif
 #else
-#if	defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
-	defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \
-	defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
-	defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5)
+#ifdef CONFIG_AT91FAMILY
 	macb_writel(macb, USRIO, MACB_BIT(CLKEN));
 #else
 	macb_writel(macb, USRIO, MACB_BIT(MII));
 #endif
 #endif /* CONFIG_RMII */
+	}
 
 	if (!macb_phy_init(macb))
 		return -1;
@@ -527,11 +589,48 @@
 	return 0;
 }
 
+static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
+{
+	u32 config;
+	unsigned long macb_hz = get_macb_pclk_rate(id);
+
+	if (macb_hz < 20000000)
+		config = MACB_BF(CLK, MACB_CLK_DIV8);
+	else if (macb_hz < 40000000)
+		config = MACB_BF(CLK, MACB_CLK_DIV16);
+	else if (macb_hz < 80000000)
+		config = MACB_BF(CLK, MACB_CLK_DIV32);
+	else
+		config = MACB_BF(CLK, MACB_CLK_DIV64);
+
+	return config;
+}
+
+static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
+{
+	u32 config;
+	unsigned long macb_hz = get_macb_pclk_rate(id);
+
+	if (macb_hz < 20000000)
+		config = GEM_BF(CLK, GEM_CLK_DIV8);
+	else if (macb_hz < 40000000)
+		config = GEM_BF(CLK, GEM_CLK_DIV16);
+	else if (macb_hz < 80000000)
+		config = GEM_BF(CLK, GEM_CLK_DIV32);
+	else if (macb_hz < 120000000)
+		config = GEM_BF(CLK, GEM_CLK_DIV48);
+	else if (macb_hz < 160000000)
+		config = GEM_BF(CLK, GEM_CLK_DIV64);
+	else
+		config = GEM_BF(CLK, GEM_CLK_DIV96);
+
+	return config;
+}
+
 int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
 {
 	struct macb_device *macb;
 	struct eth_device *netdev;
-	unsigned long macb_hz;
 	u32 ncfgr;
 
 	macb = malloc(sizeof(struct macb_device));
@@ -555,7 +654,11 @@
 	macb->regs = regs;
 	macb->phy_addr = phy_addr;
 
-	sprintf(netdev->name, "macb%d", id);
+	if (macb_is_gem(macb))
+		sprintf(netdev->name, "gmac%d", id);
+	else
+		sprintf(netdev->name, "macb%d", id);
+
 	netdev->init = macb_init;
 	netdev->halt = macb_halt;
 	netdev->send = macb_send;
@@ -566,22 +669,20 @@
 	 * Do some basic initialization so that we at least can talk
 	 * to the PHY
 	 */
-	macb_hz = get_macb_pclk_rate(id);
-	if (macb_hz < 20000000)
-		ncfgr = MACB_BF(CLK, MACB_CLK_DIV8);
-	else if (macb_hz < 40000000)
-		ncfgr = MACB_BF(CLK, MACB_CLK_DIV16);
-	else if (macb_hz < 80000000)
-		ncfgr = MACB_BF(CLK, MACB_CLK_DIV32);
-	else
-		ncfgr = MACB_BF(CLK, MACB_CLK_DIV64);
+	if (macb_is_gem(macb)) {
+		ncfgr = gem_mdc_clk_div(id, macb);
+		ncfgr |= GEM_BF(DBW, 1);
+	} else {
+		ncfgr = macb_mdc_clk_div(id, macb);
+	}
 
 	macb_writel(macb, NCFGR, ncfgr);
 
 	eth_register(netdev);
 
-#if defined(CONFIG_CMD_MII)
+#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 	miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
+	macb->bus = miiphy_get_dev_by_name(netdev->name);
 #endif
 	return 0;
 }
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index f92a20c..68eef00 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -26,6 +26,7 @@
 #define MACB_NCR				0x0000
 #define MACB_NCFGR				0x0004
 #define MACB_NSR				0x0008
+#define GEM_UR					0x000c
 #define MACB_TSR				0x0014
 #define MACB_RBQP				0x0018
 #define MACB_TBQP				0x001c
@@ -71,6 +72,7 @@
 #define MACB_TPQ				0x00bc
 #define MACB_USRIO				0x00c0
 #define MACB_WOL				0x00c4
+#define MACB_MID				0x00fc
 
 /* Bitfields in NCR */
 #define MACB_LB_OFFSET				0
@@ -138,6 +140,13 @@
 #define MACB_IRXFCS_OFFSET			19
 #define MACB_IRXFCS_SIZE			1
 
+#define GEM_GBE_OFFSET				10
+#define GEM_GBE_SIZE				1
+#define GEM_CLK_OFFSET				18
+#define GEM_CLK_SIZE				3
+#define GEM_DBW_OFFSET				21
+#define GEM_DBW_SIZE				2
+
 /* Bitfields in NSR */
 #define MACB_NSR_LINK_OFFSET			0
 #define MACB_NSR_LINK_SIZE			1
@@ -146,6 +155,10 @@
 #define MACB_IDLE_OFFSET			2
 #define MACB_IDLE_SIZE				1
 
+/* Bitfields in UR */
+#define GEM_RGMII_OFFSET			0
+#define GEM_RGMII_SIZE				1
+
 /* Bitfields in TSR */
 #define MACB_UBR_OFFSET				0
 #define MACB_UBR_SIZE				1
@@ -240,12 +253,25 @@
 #define MACB_WOL_MTI_OFFSET			19
 #define MACB_WOL_MTI_SIZE			1
 
+/* Bitfields in MID */
+#define MACB_IDNUM_OFFSET			16
+#define MACB_IDNUM_SIZE				16
+
+/* Bitfields in DCFG1 */
 /* Constants for CLK */
 #define MACB_CLK_DIV8				0
 #define MACB_CLK_DIV16				1
 #define MACB_CLK_DIV32				2
 #define MACB_CLK_DIV64				3
 
+/* GEM specific constants for CLK */
+#define GEM_CLK_DIV8				0
+#define GEM_CLK_DIV16				1
+#define GEM_CLK_DIV32				2
+#define GEM_CLK_DIV48				3
+#define GEM_CLK_DIV64				4
+#define GEM_CLK_DIV96				5
+
 /* Constants for MAN register */
 #define MACB_MAN_SOF				1
 #define MACB_MAN_WRITE				1
@@ -255,21 +281,38 @@
 /* Bit manipulation macros */
 #define MACB_BIT(name)					\
 	(1 << MACB_##name##_OFFSET)
-#define MACB_BF(name,value)				\
+#define MACB_BF(name, value)				\
 	(((value) & ((1 << MACB_##name##_SIZE) - 1))	\
 	 << MACB_##name##_OFFSET)
-#define MACB_BFEXT(name,value)\
+#define MACB_BFEXT(name, value)\
 	(((value) >> MACB_##name##_OFFSET)		\
 	 & ((1 << MACB_##name##_SIZE) - 1))
-#define MACB_BFINS(name,value,old)			\
+#define MACB_BFINS(name, value, old)			\
 	(((old) & ~(((1 << MACB_##name##_SIZE) - 1)	\
 		    << MACB_##name##_OFFSET))		\
-	 | MACB_BF(name,value))
+	 | MACB_BF(name, value))
+
+#define GEM_BIT(name)					\
+	(1 << GEM_##name##_OFFSET)
+#define GEM_BF(name, value)				\
+	(((value) & ((1 << GEM_##name##_SIZE) - 1))	\
+	 << GEM_##name##_OFFSET)
+#define GEM_BFEXT(name, value)\
+	(((value) >> GEM_##name##_OFFSET)		\
+	 & ((1 << GEM_##name##_SIZE) - 1))
+#define GEM_BFINS(name, value, old)			\
+	(((old) & ~(((1 << GEM_##name##_SIZE) - 1)	\
+		    << GEM_##name##_OFFSET))		\
+	 | GEM_BF(name, value))
 
 /* Register access macros */
-#define macb_readl(port,reg)				\
+#define macb_readl(port, reg)				\
 	readl((port)->regs + MACB_##reg)
-#define macb_writel(port,reg,value)			\
+#define macb_writel(port, reg, value)			\
 	writel((value), (port)->regs + MACB_##reg)
+#define gem_readl(port, reg)				\
+	readl((port)->regs + GEM_##reg)
+#define gem_writel(port, reg, value)			\
+	writel((value), (port)->regs + GEM_##reg)
 
 #endif /* __DRIVERS_MACB_H__ */
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index 47bf27c..319fe8a 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -43,6 +43,8 @@
 #include <asm/arch/kirkwood.h>
 #elif defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
+#elif defined(CONFIG_DOVE)
+#include <asm/arch/dove.h>
 #endif
 
 #include "mvgbe.h"
@@ -52,7 +54,7 @@
 #define MV_PHY_ADR_REQUEST 0xee
 #define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 /*
  * smi_reg_read - miiphy_read callback function.
  *
@@ -184,6 +186,25 @@
 }
 #endif
 
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
+		   int reg_addr)
+{
+	u16 data;
+	int ret;
+	ret = smi_reg_read(bus->name, phy_addr, reg_addr, &data);
+	if (ret)
+		return ret;
+	return data;
+}
+
+int mvgbe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
+		    int reg_addr, u16 data)
+{
+	return smi_reg_write(bus->name, phy_addr, reg_addr, data);
+}
+#endif
+
 /* Stop and checks all queues */
 static void stop_queue(u32 * qreg)
 {
@@ -467,8 +488,9 @@
 	/* Enable port Rx. */
 	MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
 
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
-	 && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
+	!defined(CONFIG_PHYLIB) && \
+	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
 	/* Wait up to 5s for the link status */
 	for (i = 0; i < 5; i++) {
 		u16 phyadr;
@@ -647,6 +669,45 @@
 	return 0;
 }
 
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phylib_init(struct eth_device *dev, int phyid)
+{
+	struct mii_dev *bus;
+	struct phy_device *phydev;
+	int ret;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		printf("mdio_alloc failed\n");
+		return -ENOMEM;
+	}
+	bus->read = mvgbe_phy_read;
+	bus->write = mvgbe_phy_write;
+	sprintf(bus->name, dev->name);
+
+	ret = mdio_register(bus);
+	if (ret) {
+		printf("mdio_register failed\n");
+		free(bus);
+		return -ENOMEM;
+	}
+
+	/* Set phy address of the port */
+	mvgbe_phy_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
+
+	phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
+	if (!phydev) {
+		printf("phy_connect failed\n");
+		return -ENODEV;
+	}
+
+	phy_config(phydev);
+	phy_startup(phydev);
+
+	return 0;
+}
+#endif
+
 int mvgbe_initialize(bd_t *bis)
 {
 	struct mvgbe_device *dmvgbe;
@@ -729,7 +790,9 @@
 
 		eth_register(dev);
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#if defined(CONFIG_PHYLIB)
+		mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
+#elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 		miiphy_register(dev->name, smi_reg_read, smi_reg_write);
 		/* Set phy address of the port */
 		miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h
index d8a5429..7f5d98f 100644
--- a/drivers/net/mvgbe.h
+++ b/drivers/net/mvgbe.h
@@ -308,10 +308,17 @@
 #define EBAR_TARGET_GUNIT			0x00000007
 
 /* Window attrib */
+#if defined(CONFIG_DOVE)
+#define EBAR_DRAM_CS0				0x00000000
+#define EBAR_DRAM_CS1				0x00000000
+#define EBAR_DRAM_CS2				0x00000000
+#define EBAR_DRAM_CS3				0x00000000
+#else
 #define EBAR_DRAM_CS0				0x00000E00
 #define EBAR_DRAM_CS1				0x00000D00
 #define EBAR_DRAM_CS2				0x00000B00
 #define EBAR_DRAM_CS3				0x00000700
+#endif
 
 /* DRAM Target interface */
 #define EBAR_DRAM_NO_CACHE_COHERENCY		0x00000000
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index af5f4b8..695873e 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -35,6 +35,7 @@
 COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o
 COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
 COBJS-$(CONFIG_PHY_ET1011C) += et1011c.o
+COBJS-$(CONFIG_PHY_ICPLUS) += icplus.o
 COBJS-$(CONFIG_PHY_LXT) += lxt.o
 COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
 COBJS-$(CONFIG_PHY_MICREL) += micrel.o
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index 9b3808b..09d4879 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -16,7 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  *
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011, 2013 Freescale Semiconductor, Inc.
  * author Andy Fleming
  *
  */
@@ -30,6 +30,27 @@
 	return 0;
 }
 
+static int ar8035_config(struct phy_device *phydev)
+{
+	int regval;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
+	regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018));
+
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
+	regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100));
+
+	genphy_config_aneg(phydev);
+
+	phy_reset(phydev);
+
+	return 0;
+}
+
 static struct phy_driver AR8021_driver =  {
 	.name = "AR8021",
 	.uid = 0x4dd040,
@@ -40,9 +61,31 @@
 	.shutdown = genphy_shutdown,
 };
 
+static struct phy_driver AR8031_driver =  {
+	.name = "AR8031",
+	.uid = 0x4dd074,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = genphy_config,
+	.startup = genphy_startup,
+	.shutdown = genphy_shutdown,
+};
+
+static struct phy_driver AR8035_driver =  {
+	.name = "AR8035",
+	.uid = 0x4dd072,
+	.mask = 0x4fffff,
+	.features = PHY_GBIT_FEATURES,
+	.config = ar8035_config,
+	.startup = genphy_startup,
+	.shutdown = genphy_shutdown,
+};
+
 int phy_atheros_init(void)
 {
 	phy_register(&AR8021_driver);
+	phy_register(&AR8031_driver);
+	phy_register(&AR8035_driver);
 
 	return 0;
 }
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644
index 0000000..dd5c592
--- /dev/null
+++ b/drivers/net/phy/icplus.c
@@ -0,0 +1,94 @@
+/*
+ * ICPlus PHY drivers
+ *
+ * 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
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ */
+#include <phy.h>
+
+/* IP101A/G - IP1001 */
+#define IP10XX_SPEC_CTRL_STATUS         16      /* Spec. Control Register */
+#define IP1001_SPEC_CTRL_STATUS_2       20      /* IP1001 Spec. Control Reg 2 */
+#define IP1001_PHASE_SEL_MASK           3       /* IP1001 RX/TXPHASE_SEL */
+#define IP1001_APS_ON                   11      /* IP1001 APS Mode  bit */
+#define IP101A_G_APS_ON                 2       /* IP101A/G APS Mode bit */
+#define IP101A_G_IRQ_CONF_STATUS        0x11    /* Conf Info IRQ & Status Reg */
+#define IP101A_G_IRQ_PIN_USED           (1<<15) /* INTR pin used */
+#define IP101A_G_IRQ_DEFAULT            IP101A_G_IRQ_PIN_USED
+
+static int ip1001_config(struct phy_device *phydev)
+{
+	int c;
+
+	/* Enable Auto Power Saving mode */
+	c = phy_read(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2);
+	if (c < 0)
+		return c;
+	c |= IP1001_APS_ON;
+	c = phy_write(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2, c);
+	if (c < 0)
+		return c;
+
+	/* INTR pin used: speed/link/duplex will cause an interrupt */
+	c = phy_write(phydev, MDIO_DEVAD_NONE, IP101A_G_IRQ_CONF_STATUS,
+		      IP101A_G_IRQ_DEFAULT);
+	if (c < 0)
+		return c;
+
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+		/*
+		 * Additional delay (2ns) used to adjust RX clock phase
+		 * at RGMII interface
+		 */
+		c = phy_read(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS);
+		if (c < 0)
+			return c;
+
+		c |= IP1001_PHASE_SEL_MASK;
+		c = phy_write(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS,
+			      c);
+		if (c < 0)
+			return c;
+	}
+
+	return 0;
+}
+
+static int ip1001_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	genphy_parse_link(phydev);
+
+	return 0;
+}
+static struct phy_driver IP1001_driver = {
+	.name = "ICPlus IP1001",
+	.uid = 0x02430d90,
+	.mask = 0x0ffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &ip1001_config,
+	.startup = &ip1001_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_icplus_init(void)
+{
+	phy_register(&IP1001_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 46801c7..8397e32 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -89,6 +89,12 @@
 
 #define MIIM_88E1149_PHY_PAGE	29
 
+/* 88E1310 PHY defines */
+#define MIIM_88E1310_PHY_LED_CTRL	16
+#define MIIM_88E1310_PHY_IRQ_EN		18
+#define MIIM_88E1310_PHY_RGMII_CTRL	21
+#define MIIM_88E1310_PHY_PAGE		22
+
 /* Marvell 88E1011S */
 static int m88e1011s_config(struct phy_device *phydev)
 {
@@ -394,6 +400,37 @@
 	return 0;
 }
 
+/* Marvell 88E1310 */
+static int m88e1310_config(struct phy_device *phydev)
+{
+	u16 reg;
+
+	/* LED link and activity */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL);
+	reg = (reg & ~0xf) | 0x1;
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg);
+
+	/* Set LED2/INT to INT mode, low active */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN);
+	reg = (reg & 0x77ff) | 0x0880;
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg);
+
+	/* Set RGMII delay */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL);
+	reg |= 0x0030;
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg);
+
+	/* Ensure to return to page 0 */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000);
+
+	genphy_config_aneg(phydev);
+	phy_reset(phydev);
+
+	return 0;
+}
 
 static struct phy_driver M88E1011S_driver = {
 	.name = "Marvell 88E1011S",
@@ -475,8 +512,19 @@
 	.shutdown = &genphy_shutdown,
 };
 
+static struct phy_driver M88E1310_driver = {
+	.name = "Marvell 88E1310",
+	.uid = 0x01410e90,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1310_config,
+	.startup = &m88e1011s_startup,
+	.shutdown = &genphy_shutdown,
+};
+
 int phy_marvell_init(void)
 {
+	phy_register(&M88E1310_driver);
 	phy_register(&M88E1149S_driver);
 	phy_register(&M88E1145_driver);
 	phy_register(&M88E1121R_driver);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 30f3264..aa9cbcf 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -18,6 +18,7 @@
  *
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
+ * (C) 2012 NetModule AG, David Andrey, added KSZ9031
  *
  */
 #include <config.h>
@@ -52,16 +53,46 @@
 };
 #endif
 
+
+/**
+ * KSZ9021 - KSZ9031 common
+ */
+
+#define MII_KSZ90xx_PHY_CTL		0x1f
+#define MIIM_KSZ90xx_PHYCTL_1000	(1 << 6)
+#define MIIM_KSZ90xx_PHYCTL_100		(1 << 5)
+#define MIIM_KSZ90xx_PHYCTL_10		(1 << 4)
+#define MIIM_KSZ90xx_PHYCTL_DUPLEX	(1 << 3)
+
+static int ksz90xx_startup(struct phy_device *phydev)
+{
+	unsigned phy_ctl;
+	genphy_update_link(phydev);
+	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
+
+	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
+		phydev->speed = SPEED_1000;
+	else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
+		phydev->speed = SPEED_100;
+	else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
+		phydev->speed = SPEED_10;
+	return 0;
+}
 #ifdef CONFIG_PHY_MICREL_KSZ9021
-/* ksz9021 PHY Registers */
+
+/*
+ * KSZ9021
+ */
+
+/* PHY Registers */
 #define MII_KSZ9021_EXTENDED_CTRL	0x0b
 #define MII_KSZ9021_EXTENDED_DATAW	0x0c
 #define MII_KSZ9021_EXTENDED_DATAR	0x0d
-#define MII_KSZ9021_PHY_CTL		0x1f
-#define MIIM_KSZ9021_PHYCTL_1000	(1 << 6)
-#define MIIM_KSZ9021_PHYCTL_100		(1 << 5)
-#define MIIM_KSZ9021_PHYCTL_10		(1 << 4)
-#define MIIM_KSZ9021_PHYCTL_DUPLEX	(1 << 3)
 
 #define CTRL1000_PREFER_MASTER		(1 << 10)
 #define CTRL1000_CONFIG_MASTER		(1 << 11)
@@ -106,37 +137,64 @@
 	return 0;
 }
 
-static int ksz9021_startup(struct phy_device *phydev)
-{
-	unsigned phy_ctl;
-	genphy_update_link(phydev);
-	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_PHY_CTL);
-
-	if (phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX)
-		phydev->duplex = DUPLEX_FULL;
-	else
-		phydev->duplex = DUPLEX_HALF;
-
-	if (phy_ctl & MIIM_KSZ9021_PHYCTL_1000)
-		phydev->speed = SPEED_1000;
-	else if (phy_ctl & MIIM_KSZ9021_PHYCTL_100)
-		phydev->speed = SPEED_100;
-	else if (phy_ctl & MIIM_KSZ9021_PHYCTL_10)
-		phydev->speed = SPEED_10;
-	return 0;
-}
-
 static struct phy_driver ksz9021_driver = {
 	.name = "Micrel ksz9021",
 	.uid  = 0x221610,
 	.mask = 0xfffff0,
 	.features = PHY_GBIT_FEATURES,
 	.config = &ksz9021_config,
-	.startup = &ksz9021_startup,
+	.startup = &ksz90xx_startup,
 	.shutdown = &genphy_shutdown,
 };
 #endif
 
+/**
+ * KSZ9031
+ */
+/* PHY Registers */
+#define MII_KSZ9031_MMD_ACCES_CTRL	0x0d
+#define MII_KSZ9031_MMD_REG_DATA	0x0e
+
+/* Accessors to extended registers*/
+int ksz9031_phy_extended_write(struct phy_device *phydev,
+			       int devaddr, int regnum, u16 mode, u16 val)
+{
+	/*select register addr for mmd*/
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
+	/*select register for mmd*/
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MII_KSZ9031_MMD_REG_DATA, regnum);
+	/*setup mode*/
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
+	/*write the value*/
+	return	phy_write(phydev, MDIO_DEVAD_NONE,
+		MII_KSZ9031_MMD_REG_DATA, val);
+}
+
+int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
+			      int regnum, u16 mode)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MII_KSZ9031_MMD_REG_DATA, regnum);
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
+	return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
+}
+
+static struct phy_driver ksz9031_driver = {
+	.name = "Micrel ksz9031",
+	.uid  = 0x221620,
+	.mask = 0xfffffe,
+	.features = PHY_GBIT_FEATURES,
+	.config   = &genphy_config,
+	.startup  = &ksz90xx_startup,
+	.shutdown = &genphy_shutdown,
+};
+
 int phy_micrel_init(void)
 {
 	phy_register(&KSZ804_driver);
@@ -145,5 +203,6 @@
 #else
 	phy_register(&KS8721_driver);
 #endif
+	phy_register(&ksz9031_driver);
 	return 0;
 }
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
index ea60ac1..6dc7ed5 100644
--- a/drivers/net/phy/natsemi.c
+++ b/drivers/net/phy/natsemi.c
@@ -22,6 +22,42 @@
  */
 #include <phy.h>
 
+/* NatSemi DP83630 */
+
+#define DP83630_PHY_PAGESEL_REG		0x13
+#define DP83630_PHY_PTP_COC_REG		0x14
+#define DP83630_PHY_PTP_CLKOUT_EN	(1<<15)
+#define DP83630_PHY_RBR_REG		0x17
+
+static int dp83630_config(struct phy_device *phydev)
+{
+	int ptp_coc_reg;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+	phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0x6);
+	ptp_coc_reg = phy_read(phydev, MDIO_DEVAD_NONE,
+			       DP83630_PHY_PTP_COC_REG);
+	ptp_coc_reg &= ~DP83630_PHY_PTP_CLKOUT_EN;
+	phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PTP_COC_REG,
+		  ptp_coc_reg);
+	phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static struct phy_driver DP83630_driver = {
+	.name = "NatSemi DP83630",
+	.uid = 0x20005ce1,
+	.mask = 0xfffffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &dp83630_config,
+	.startup = &genphy_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+
 /* DP83865 Link and Auto-Neg Status Register */
 #define MIIM_DP83865_LANR      0x11
 #define MIIM_DP83865_SPD_MASK  0x0018
@@ -90,6 +126,7 @@
 
 int phy_natsemi_init(void)
 {
+	phy_register(&DP83630_driver);
 	phy_register(&DP83865_driver);
 
 	return 0;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f8c5481..7c0eaec 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -75,6 +75,10 @@
 		adv |= ADVERTISE_PAUSE_CAP;
 	if (advertise & ADVERTISED_Asym_Pause)
 		adv |= ADVERTISE_PAUSE_ASYM;
+	if (advertise & ADVERTISED_1000baseX_Half)
+		adv |= ADVERTISE_1000XHALF;
+	if (advertise & ADVERTISED_1000baseX_Full)
+		adv |= ADVERTISE_1000XFULL;
 
 	if (adv != oldadv) {
 		err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv);
@@ -280,7 +284,7 @@
  *
  * Stolen from Linux's mii.c and phy_device.c
  */
-static int genphy_parse_link(struct phy_device *phydev)
+int genphy_parse_link(struct phy_device *phydev)
 {
 	int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
 
@@ -288,6 +292,7 @@
 	if (mii_reg & BMSR_ANEGCAPABLE) {
 		u32 lpa = 0;
 		u32 gblpa = 0;
+		u32 estatus = 0;
 
 		/* Check for gigabit capability */
 		if (mii_reg & BMSR_ERCAP) {
@@ -327,6 +332,18 @@
 
 		} else if (lpa & LPA_10FULL)
 			phydev->duplex = DUPLEX_FULL;
+
+		if (mii_reg & BMSR_ESTATEN)
+			estatus = phy_read(phydev, MDIO_DEVAD_NONE,
+					   MII_ESTATUS);
+
+		if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_XHALF |
+				ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) {
+			phydev->speed = SPEED_1000;
+			if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_TFULL))
+				phydev->duplex = DUPLEX_FULL;
+		}
+
 	} else {
 		u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
 
@@ -384,6 +401,10 @@
 			features |= SUPPORTED_1000baseT_Full;
 		if (val & ESTATUS_1000_THALF)
 			features |= SUPPORTED_1000baseT_Half;
+		if (val & ESTATUS_1000_XFULL)
+			features |= SUPPORTED_1000baseX_Full;
+		if (val & ESTATUS_1000_XHALF)
+			features |= SUPPORTED_1000baseX_Full;
 	}
 
 	phydev->supported = features;
@@ -433,6 +454,9 @@
 #ifdef CONFIG_PHY_ET1011C
 	phy_et1011c_init();
 #endif
+#ifdef CONFIG_PHY_ICPLUS
+	phy_icplus_init();
+#endif
 #ifdef CONFIG_PHY_LXT
 	phy_lxt_init();
 #endif
diff --git a/drivers/net/sunxi_wemac.c b/drivers/net/sunxi_wemac.c
new file mode 100644
index 0000000..1db3529
--- /dev/null
+++ b/drivers/net/sunxi_wemac.c
@@ -0,0 +1,533 @@
+/*
+ * sunxi_wemac.c -- Allwinner A10 ethernet driver
+ *
+ * (C) Copyright 2012, Stefan Roese <sr@denx.de>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+
+/* EMAC register  */
+struct wemac_regs {
+	u32 ctl;	/* 0x00 */
+	u32 tx_mode;	/* 0x04 */
+	u32 tx_flow;	/* 0x08 */
+	u32 tx_ctl0;	/* 0x0c */
+	u32 tx_ctl1;	/* 0x10 */
+	u32 tx_ins;	/* 0x14 */
+	u32 tx_pl0;	/* 0x18 */
+	u32 tx_pl1;	/* 0x1c */
+	u32 tx_sta;	/* 0x20 */
+	u32 tx_io_data;	/* 0x24 */
+	u32 tx_io_data1; /* 0x28 */
+	u32 tx_tsvl0;	/* 0x2c */
+	u32 tx_tsvh0;	/* 0x30 */
+	u32 tx_tsvl1;	/* 0x34 */
+	u32 tx_tsvh1;	/* 0x38 */
+	u32 rx_ctl;	/* 0x3c */
+	u32 rx_hash0;	/* 0x40 */
+	u32 rx_hash1;	/* 0x44 */
+	u32 rx_sta;	/* 0x48 */
+	u32 rx_io_data;	/* 0x4c */
+	u32 rx_fbc;	/* 0x50 */
+	u32 int_ctl;	/* 0x54 */
+	u32 int_sta;	/* 0x58 */
+	u32 mac_ctl0;	/* 0x5c */
+	u32 mac_ctl1;	/* 0x60 */
+	u32 mac_ipgt;	/* 0x64 */
+	u32 mac_ipgr;	/* 0x68 */
+	u32 mac_clrt;	/* 0x6c */
+	u32 mac_maxf;	/* 0x70 */
+	u32 mac_supp;	/* 0x74 */
+	u32 mac_test;	/* 0x78 */
+	u32 mac_mcfg;	/* 0x7c */
+	u32 mac_mcmd;	/* 0x80 */
+	u32 mac_madr;	/* 0x84 */
+	u32 mac_mwtd;	/* 0x88 */
+	u32 mac_mrdd;	/* 0x8c */
+	u32 mac_mind;	/* 0x90 */
+	u32 mac_ssrr;	/* 0x94 */
+	u32 mac_a0;	/* 0x98 */
+	u32 mac_a1;	/* 0x9c */
+};
+
+/* SRAMC register  */
+struct sunxi_sramc_regs {
+	u32 ctrl0;
+	u32 ctrl1;
+};
+
+/* 0: Disable       1: Aborted frame enable(default) */
+#define EMAC_TX_AB_M		(0x1 << 0)
+/* 0: CPU           1: DMA(default) */
+#define EMAC_TX_TM		(0x1 << 1)
+
+#define EMAC_TX_SETUP		(0)
+
+/* 0: DRQ asserted  1: DRQ automatically(default) */
+#define EMAC_RX_DRQ_MODE	(0x1 << 1)
+/* 0: CPU           1: DMA(default) */
+#define EMAC_RX_TM		(0x1 << 2)
+/* 0: Normal(default)        1: Pass all Frames */
+#define EMAC_RX_PA		(0x1 << 4)
+/* 0: Normal(default)        1: Pass Control Frames */
+#define EMAC_RX_PCF		(0x1 << 5)
+/* 0: Normal(default)        1: Pass Frames with CRC Error */
+#define EMAC_RX_PCRCE		(0x1 << 6)
+/* 0: Normal(default)        1: Pass Frames with Length Error */
+#define EMAC_RX_PLE		(0x1 << 7)
+/* 0: Normal                 1: Pass Frames length out of range(default) */
+#define EMAC_RX_POR		(0x1 << 8)
+/* 0: Not accept             1: Accept unicast Packets(default) */
+#define EMAC_RX_UCAD		(0x1 << 16)
+/* 0: Normal(default)        1: DA Filtering */
+#define EMAC_RX_DAF		(0x1 << 17)
+/* 0: Not accept             1: Accept multicast Packets(default) */
+#define EMAC_RX_MCO		(0x1 << 20)
+/* 0: Disable(default)       1: Enable Hash filter */
+#define EMAC_RX_MHF		(0x1 << 21)
+/* 0: Not accept             1: Accept Broadcast Packets(default) */
+#define EMAC_RX_BCO		(0x1 << 22)
+/* 0: Disable(default)       1: Enable SA Filtering */
+#define EMAC_RX_SAF		(0x1 << 24)
+/* 0: Normal(default)        1: Inverse Filtering */
+#define EMAC_RX_SAIF		(0x1 << 25)
+
+#define EMAC_RX_SETUP		(EMAC_RX_POR | EMAC_RX_UCAD | EMAC_RX_DAF | \
+				 EMAC_RX_MCO | EMAC_RX_BCO)
+
+/* 0: Disable                1: Enable Receive Flow Control(default) */
+#define EMAC_MAC_CTL0_RFC	(0x1 << 2)
+/* 0: Disable                1: Enable Transmit Flow Control(default) */
+#define EMAC_MAC_CTL0_TFC	(0x1 << 3)
+
+#define EMAC_MAC_CTL0_SETUP	(EMAC_MAC_CTL0_RFC | EMAC_MAC_CTL0_TFC)
+
+/* 0: Disable                1: Enable MAC Frame Length Checking(default) */
+#define EMAC_MAC_CTL1_FLC	(0x1 << 1)
+/* 0: Disable(default)       1: Enable Huge Frame */
+#define EMAC_MAC_CTL1_HF	(0x1 << 2)
+/* 0: Disable(default)       1: Enable MAC Delayed CRC */
+#define EMAC_MAC_CTL1_DCRC	(0x1 << 3)
+/* 0: Disable                1: Enable MAC CRC(default) */
+#define EMAC_MAC_CTL1_CRC	(0x1 << 4)
+/* 0: Disable                1: Enable MAC PAD Short frames(default) */
+#define EMAC_MAC_CTL1_PC	(0x1 << 5)
+/* 0: Disable(default)       1: Enable MAC PAD Short frames and append CRC */
+#define EMAC_MAC_CTL1_VC	(0x1 << 6)
+/* 0: Disable(default)       1: Enable MAC auto detect Short frames */
+#define EMAC_MAC_CTL1_ADP	(0x1 << 7)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_PRE	(0x1 << 8)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_LPE	(0x1 << 9)
+/* 0: Disable(default)       1: Enable no back off */
+#define EMAC_MAC_CTL1_NB	(0x1 << 12)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_BNB	(0x1 << 13)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_ED	(0x1 << 14)
+
+#define EMAC_MAC_CTL1_SETUP	(EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC | \
+				 EMAC_MAC_CTL1_PC)
+
+#define EMAC_MAC_IPGT		0x15
+
+#define EMAC_MAC_NBTB_IPG1	0xC
+#define EMAC_MAC_NBTB_IPG2	0x12
+
+#define EMAC_MAC_CW		0x37
+#define EMAC_MAC_RM		0xF
+
+#define EMAC_MAC_MFL		0x0600
+
+/* Receive status */
+#define EMAC_CRCERR		(1 << 4)
+#define EMAC_LENERR		(3 << 5)
+
+#define DMA_CPU_TRRESHOLD	2000
+
+struct wemac_eth_dev {
+	u32 speed;
+	u32 duplex;
+	u32 phy_configured;
+	int link_printed;
+};
+
+struct wemac_rxhdr {
+	s16 rx_len;
+	u16 rx_status;
+};
+
+static void wemac_inblk_32bit(void *reg, void *data, int count)
+{
+	int cnt = (count + 3) >> 2;
+
+	if (cnt) {
+		u32 *buf = data;
+
+		do {
+			u32 x = readl(reg);
+			*buf++ = x;
+		} while (--cnt);
+	}
+}
+
+static void wemac_outblk_32bit(void *reg, void *data, int count)
+{
+	int cnt = (count + 3) >> 2;
+
+	if (cnt) {
+		const u32 *buf = data;
+
+		do {
+			writel(*buf++, reg);
+		} while (--cnt);
+	}
+}
+
+/*
+ * Read a word from phyxcer
+ */
+static int wemac_phy_read(const char *devname, unsigned char addr,
+			  unsigned char reg, unsigned short *value)
+{
+	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	/* issue the phy address and reg */
+	writel(addr << 8 | reg, &regs->mac_madr);
+
+	/* pull up the phy io line */
+	writel(0x1, &regs->mac_mcmd);
+
+	/* Wait read complete */
+	mdelay(1);
+
+	/* push down the phy io line */
+	writel(0x0, &regs->mac_mcmd);
+
+	/* and write data */
+	*value = readl(&regs->mac_mrdd);
+
+	return 0;
+}
+
+/*
+ * Write a word to phyxcer
+ */
+static int wemac_phy_write(const char *devname, unsigned char addr,
+			   unsigned char reg, unsigned short value)
+{
+	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	/* issue the phy address and reg */
+	writel(addr << 8 | reg, &regs->mac_madr);
+
+	/* pull up the phy io line */
+	writel(0x1, &regs->mac_mcmd);
+
+	/* Wait write complete */
+	mdelay(1);
+
+	/* push down the phy io line */
+	writel(0x0, &regs->mac_mcmd);
+
+	/* and write data */
+	writel(value, &regs->mac_mwtd);
+
+	return 0;
+}
+
+static void emac_setup(struct eth_device *dev)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+	u32 reg_val;
+	u16 phy_val;
+	u32 duplex_flag;
+
+	/* Set up TX */
+	writel(EMAC_TX_SETUP, &regs->tx_mode);
+
+	/* Set up RX */
+	writel(EMAC_RX_SETUP, &regs->rx_ctl);
+
+	/* Set MAC */
+	/* Set MAC CTL0 */
+	writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
+
+	/* Set MAC CTL1 */
+	wemac_phy_read(dev->name, 1, 0, &phy_val);
+	debug("PHY SETUP, reg 0 value: %x\n", phy_val);
+	duplex_flag = !!(phy_val & (1 << 8));
+
+	reg_val = 0;
+	if (duplex_flag)
+		reg_val = (0x1 << 0);
+	writel(EMAC_MAC_CTL1_SETUP | reg_val, &regs->mac_ctl1);
+
+	/* Set up IPGT */
+	writel(EMAC_MAC_IPGT, &regs->mac_ipgt);
+
+	/* Set up IPGR */
+	writel(EMAC_MAC_NBTB_IPG2 | (EMAC_MAC_NBTB_IPG1 << 8), &regs->mac_ipgr);
+
+	/* Set up Collison window */
+	writel(EMAC_MAC_RM | (EMAC_MAC_CW << 8), &regs->mac_clrt);
+
+	/* Set up Max Frame Length */
+	writel(EMAC_MAC_MFL, &regs->mac_maxf);
+}
+
+static void wemac_reset(struct eth_device *dev)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	debug("resetting device\n");
+
+	/* RESET device */
+	writel(0, &regs->ctl);
+	udelay(200);
+
+	writel(1, &regs->ctl);
+	udelay(200);
+}
+
+static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+	struct wemac_eth_dev *priv = dev->priv;
+	u16 phy_reg;
+
+	/* Init EMAC */
+
+	/* Flush RX FIFO */
+	setbits_le32(&regs->rx_ctl, 0x8);
+	udelay(1);
+
+	/* Init MAC */
+
+	/* Soft reset MAC */
+	clrbits_le32(&regs->mac_ctl0, 1 << 15);
+
+	/* Set MII clock */
+	clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
+
+	/* Clear RX counter */
+	writel(0x0, &regs->rx_fbc);
+	udelay(1);
+
+	/* Set up EMAC */
+	emac_setup(dev);
+
+	writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 |
+	       dev->enetaddr[2], &regs->mac_a1);
+	writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 |
+	       dev->enetaddr[5], &regs->mac_a0);
+
+	mdelay(1);
+
+	wemac_reset(dev);
+
+	/* PHY POWER UP */
+	wemac_phy_read(dev->name, 1, 0, &phy_reg);
+	wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11)));
+	mdelay(1);
+
+	wemac_phy_read(dev->name, 1, 0, &phy_reg);
+
+	priv->speed = miiphy_speed(dev->name, 0);
+	priv->duplex = miiphy_duplex(dev->name, 0);
+
+	/* Print link status only once */
+	if (!priv->link_printed) {
+		printf("ENET Speed is %d Mbps - %s duplex connection\n",
+		       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
+		priv->link_printed = 1;
+	}
+
+	/* Set EMAC SPEED depend on PHY */
+	clrsetbits_le32(&regs->mac_supp, 1 << 8,
+			((phy_reg & (1 << 13)) >> 13) << 8);
+
+	/* Set duplex depend on phy */
+	clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
+			((phy_reg & (1 << 8)) >> 8) << 0);
+
+	/* Enable RX/TX */
+	setbits_le32(&regs->ctl, 0x7);
+
+	return 0;
+}
+
+static void sunxi_wemac_eth_halt(struct eth_device *dev)
+{
+	/* Nothing to do here */
+}
+
+static int sunxi_wemac_eth_recv(struct eth_device *dev)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+	struct wemac_rxhdr rxhdr;
+	u32 rxcount;
+	u32 reg_val;
+	int rx_len;
+	int rx_status;
+	int good_packet;
+
+	/* Check packet ready or not */
+
+	/*
+	 * Race warning: The first packet might arrive with
+	 * the interrupts disabled, but the second will fix
+	 */
+	rxcount = readl(&regs->rx_fbc);
+	if (!rxcount) {
+		/* Had one stuck? */
+		rxcount = readl(&regs->rx_fbc);
+		if (!rxcount)
+			return 0;
+	}
+
+	reg_val = readl(&regs->rx_io_data);
+	if (reg_val != 0x0143414d) {
+		/* Disable RX */
+		clrbits_le32(&regs->ctl, 1 << 2);
+
+		/* Flush RX FIFO */
+		setbits_le32(&regs->rx_ctl, 1 << 3);
+		while (readl(&regs->rx_ctl) & (1 << 3))
+			;
+
+		/* Enable RX */
+		setbits_le32(&regs->ctl, 1 << 2);
+
+		return 0;
+	}
+
+	/*
+	 * A packet ready now
+	 * Get status/length
+	 */
+	good_packet = 1;
+
+	wemac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
+
+	rx_len = rxhdr.rx_len;
+	rx_status = rxhdr.rx_status;
+
+	/* Packet Status check */
+	if (rx_len < 0x40) {
+		good_packet = 0;
+		debug("RX: Bad Packet (runt)\n");
+	}
+
+	/* rx_status is identical to RSR register. */
+	if (0 & rx_status & (EMAC_CRCERR | EMAC_LENERR)) {
+		good_packet = 0;
+		if (rx_status & EMAC_CRCERR)
+			printf("crc error\n");
+		if (rx_status & EMAC_LENERR)
+			printf("length error\n");
+	}
+
+	/* Move data from WEMAC */
+	if (good_packet) {
+		if (rx_len > DMA_CPU_TRRESHOLD) {
+			printf("Received packet is too big (len=%d)\n", rx_len);
+		} else {
+			wemac_inblk_32bit((void *)&regs->rx_io_data,
+					  NetRxPackets[0], rx_len);
+
+			/* Pass to upper layer */
+			NetReceive(NetRxPackets[0], rx_len);
+			return rx_len;
+		}
+	}
+
+	return 0;
+}
+
+static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	/* Select channel 0 */
+	writel(0, &regs->tx_ins);
+
+	/* Write packet */
+	wemac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
+
+	/* Set TX len */
+	writel(len, &regs->tx_pl0);
+
+	/* Start translate from fifo to phy */
+	setbits_le32(&regs->tx_ctl0, 1);
+
+	return 0;
+}
+
+int sunxi_wemac_initialize(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_sramc_regs *sram =
+		(struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
+	struct eth_device *dev;
+	struct wemac_eth_dev *priv;
+	int pin;
+
+	dev = malloc(sizeof(*dev));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev));
+	if (!priv) {
+		free(dev);
+		return -ENOMEM;
+	}
+
+	memset(dev, 0, sizeof(*dev));
+	memset(priv, 0, sizeof(struct wemac_eth_dev));
+
+	/* Map SRAM to EMAC */
+	setbits_le32(&sram->ctrl1, 0x5 << 2);
+
+	/* Configure pin mux settings for MII Ethernet */
+	for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
+		sunxi_gpio_set_cfgpin(pin, 2);
+
+	/* Set up clock gating */
+	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC);
+
+	dev->iobase = SUNXI_EMAC_BASE;
+	dev->priv = priv;
+	dev->init = sunxi_wemac_eth_init;
+	dev->halt = sunxi_wemac_eth_halt;
+	dev->send = sunxi_wemac_eth_send;
+	dev->recv = sunxi_wemac_eth_recv;
+	strcpy(dev->name, "wemac");
+
+	eth_register(dev);
+
+	miiphy_register(dev->name, wemac_phy_read, wemac_phy_write);
+
+	return 0;
+}
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 77ac1f7..621c899 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -211,7 +211,7 @@
 	return 1;
 }
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 static void fsl_pcie_boot_master(pit_t *pi)
 {
 	/* configure inbound window for slave's u-boot image */
@@ -388,7 +388,7 @@
 	/* see if we are a PCIe or PCI controller */
 	pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 	/* boot from PCIE --master */
 	char *s = getenv("bootmaster");
 	char pcie[6];
@@ -624,7 +624,7 @@
 	if (fsl_is_pci_agent(hose)) {
 		fsl_pci_config_unlock(hose);
 		hose->last_busno = hose->first_busno;
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 	} else {
 		/* boot from PCIE --master releases slave's core 0 */
 		char *s = getenv("bootmaster");
diff --git a/drivers/power/exynos-tmu.c b/drivers/power/exynos-tmu.c
index d4b3e65..9a093a5 100644
--- a/drivers/power/exynos-tmu.c
+++ b/drivers/power/exynos-tmu.c
@@ -50,15 +50,15 @@
 /* Tmeperature threshold values for various thermal events */
 struct temperature_params {
 	/* minimum value in temperature code range */
-	unsigned int min_val;
+	unsigned min_val;
 	/* maximum value in temperature code range */
-	unsigned int max_val;
+	unsigned max_val;
 	/* temperature threshold to start warning */
-	unsigned int start_warning;
+	unsigned start_warning;
 	/* temperature threshold CPU tripping */
-	unsigned int start_tripping;
+	unsigned start_tripping;
 	/* temperature threshold for HW tripping */
-	unsigned int hardware_tripping;
+	unsigned hardware_tripping;
 };
 
 /* Pre-defined values and thresholds for calibration of current temperature */
@@ -66,25 +66,27 @@
 	/* pre-defined temperature thresholds */
 	struct temperature_params ts;
 	/* pre-defined efuse range minimum value */
-	unsigned int efuse_min_value;
+	unsigned efuse_min_value;
 	/* pre-defined efuse value for temperature calibration */
-	unsigned int efuse_value;
+	unsigned efuse_value;
 	/* pre-defined efuse range maximum value */
-	unsigned int efuse_max_value;
+	unsigned efuse_max_value;
 	/* current temperature sensing slope */
-	unsigned int slope;
+	unsigned slope;
 };
 
 /* TMU device specific details and status */
 struct tmu_info {
 	/* base Address for the TMU */
-	unsigned tmu_base;
+	struct exynos5_tmu_reg *tmu_base;
+	/* mux Address for the TMU */
+	int tmu_mux;
 	/* pre-defined values for calibration and thresholds */
 	struct tmu_data data;
 	/* value required for triminfo_25 calibration */
-	unsigned int te1;
+	unsigned te1;
 	/* value required for triminfo_85 calibration */
-	unsigned int te2;
+	unsigned te2;
 	/* Value for measured data calibration */
 	int dc_value;
 	/* enum value indicating status of the TMU */
@@ -103,17 +105,24 @@
  */
 static int get_cur_temp(struct tmu_info *info)
 {
-	int cur_temp;
-	struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base;
+	struct exynos5_tmu_reg *reg = info->tmu_base;
+	ulong start;
+	int cur_temp = 0;
 
 	/*
 	 * Temperature code range between min 25 and max 125.
 	 * May run more than once for first call as initial sensing
 	 * has not yet happened.
 	 */
-	do {
-		cur_temp = readl(&reg->current_temp) & 0xff;
-	} while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL);
+	if (info->tmu_state == TMU_STATUS_NORMAL) {
+		start = get_timer(0);
+		do {
+			cur_temp = readl(&reg->current_temp) & 0xff;
+		} while ((cur_temp == 0) || (get_timer(start) > 100));
+	}
+
+	if (cur_temp == 0)
+		return cur_temp;
 
 	/* Calibrate current temperature */
 	cur_temp = cur_temp - info->te1 + info->dc_value;
@@ -137,23 +146,29 @@
 
 	/* Read current temperature of the SOC */
 	cur_temp = get_cur_temp(&gbl_info);
+
+	if (!cur_temp)
+		goto out;
+
 	*temp = cur_temp;
 
 	/* Temperature code lies between min 25 and max 125 */
-	if (cur_temp >= data->ts.start_tripping &&
-			cur_temp <= data->ts.max_val) {
+	if ((cur_temp >= data->ts.start_tripping) &&
+	    (cur_temp <= data->ts.max_val))
 		return TMU_STATUS_TRIPPED;
-	} else if (cur_temp >= data->ts.start_warning) {
+
+	if (cur_temp >= data->ts.start_warning)
 		return TMU_STATUS_WARNING;
-	} else if (cur_temp < data->ts.start_warning &&
-			cur_temp >= data->ts.min_val) {
+
+	if ((cur_temp < data->ts.start_warning) &&
+	    (cur_temp >= data->ts.min_val))
 		return TMU_STATUS_NORMAL;
-	} else {
-		/* Temperature code does not lie between min 25 and max 125 */
-		gbl_info.tmu_state = TMU_STATUS_INIT;
-		debug("EXYNOS_TMU: Thermal reading failed\n");
-		return TMU_STATUS_INIT;
-	}
+
+ out:
+	/* Temperature code does not lie between min 25 and max 125 */
+	gbl_info.tmu_state = TMU_STATUS_INIT;
+	debug("EXYNOS_TMU: Thermal reading failed\n");
+	return TMU_STATUS_INIT;
 }
 
 /*
@@ -166,6 +181,7 @@
 static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)
 {
 #ifdef CONFIG_OF_CONTROL
+	fdt_addr_t addr;
 	int node;
 	int error = 0;
 
@@ -183,46 +199,58 @@
 	 * miscalculation of register values in tmu_setup_parameters
 	 * may result in misleading current temperature.
 	 */
-	info->tmu_base = fdtdec_get_addr(blob, node, "reg");
-	if (info->tmu_base == FDT_ADDR_T_NONE) {
+	addr = fdtdec_get_addr(blob, node, "reg");
+	if (addr == FDT_ADDR_T_NONE) {
 		debug("%s: Missing tmu-base\n", __func__);
 		return -1;
 	}
+	info->tmu_base = (struct exynos5_tmu_reg *)addr;
+
+	/* Optional field. */
+	info->tmu_mux = fdtdec_get_int(blob,
+				node, "samsung,mux", -1);
+	/* Take default value as per the user manual b(110) */
+	if (info->tmu_mux == -1)
+		info->tmu_mux = 0x6;
+
 	info->data.ts.min_val = fdtdec_get_int(blob,
 				node, "samsung,min-temp", -1);
-	error |= info->data.ts.min_val;
+	error |= (info->data.ts.min_val == -1);
 	info->data.ts.max_val = fdtdec_get_int(blob,
 				node, "samsung,max-temp", -1);
-	error |= info->data.ts.max_val;
+	error |= (info->data.ts.max_val == -1);
 	info->data.ts.start_warning = fdtdec_get_int(blob,
 				node, "samsung,start-warning", -1);
-	error |= info->data.ts.start_warning;
+	error |= (info->data.ts.start_warning == -1);
 	info->data.ts.start_tripping = fdtdec_get_int(blob,
 				node, "samsung,start-tripping", -1);
-	error |= info->data.ts.start_tripping;
+	error |= (info->data.ts.start_tripping == -1);
 	info->data.ts.hardware_tripping = fdtdec_get_int(blob,
 				node, "samsung,hw-tripping", -1);
-	error |= info->data.ts.hardware_tripping;
+	error |= (info->data.ts.hardware_tripping == -1);
 	info->data.efuse_min_value = fdtdec_get_int(blob,
 				node, "samsung,efuse-min-value", -1);
-	error |= info->data.efuse_min_value;
+	error |= (info->data.efuse_min_value == -1);
 	info->data.efuse_value = fdtdec_get_int(blob,
 				node, "samsung,efuse-value", -1);
-	error |= info->data.efuse_value;
+	error |= (info->data.efuse_value == -1);
 	info->data.efuse_max_value = fdtdec_get_int(blob,
 				node, "samsung,efuse-max-value", -1);
-	error |= info->data.efuse_max_value;
+	error |= (info->data.efuse_max_value == -1);
 	info->data.slope = fdtdec_get_int(blob,
 				node, "samsung,slope", -1);
-	error |= info->data.slope;
+	error |= (info->data.slope == -1);
 	info->dc_value = fdtdec_get_int(blob,
 				node, "samsung,dc-value", -1);
-	error |= info->dc_value;
+	error |= (info->dc_value == -1);
 
-	if (error == -1) {
+	if (error) {
 		debug("fail to get tmu node properties\n");
 		return -1;
 	}
+#else
+	/* Non DT support may never be added. Just in case  */
+	return -1;
 #endif
 
 	return 0;
@@ -236,12 +264,12 @@
  */
 static void tmu_setup_parameters(struct tmu_info *info)
 {
-	unsigned int te_code, con;
-	unsigned int warning_code, trip_code, hwtrip_code;
-	unsigned int cooling_temp;
-	unsigned int rising_value;
+	unsigned te_code, con;
+	unsigned warning_code, trip_code, hwtrip_code;
+	unsigned cooling_temp;
+	unsigned rising_value;
 	struct tmu_data *data = &info->data;
-	struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base;
+	struct exynos5_tmu_reg *reg = info->tmu_base;
 
 	/* Must reload for reading efuse value from triminfo register */
 	writel(TRIMINFO_RELOAD, &reg->triminfo_control);
@@ -288,7 +316,7 @@
 
 	/* TMU core enable */
 	con = readl(&reg->tmu_control);
-	con |= THERM_TRIP_EN | CORE_EN;
+	con |= THERM_TRIP_EN | CORE_EN | (info->tmu_mux << 20);
 
 	writel(con, &reg->tmu_control);
 
@@ -314,6 +342,5 @@
 	tmu_setup_parameters(&gbl_info);
 	gbl_info.tmu_state = TMU_STATUS_NORMAL;
 ret:
-
 	return gbl_info.tmu_state;
 }
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index daa8003..a19cec5 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -37,7 +37,6 @@
  * Table with supported baudrates (defined in config_xyz.h)
  */
 static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
-#define	N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
 
 /**
  * serial_null() - Void registration routine of a serial driver
@@ -74,11 +73,11 @@
 		if (gd->baudrate == baudrate)
 			return 0;
 
-		for (i = 0; i < N_BAUDRATES; ++i) {
+		for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
 			if (baudrate == baudrate_table[i])
 				break;
 		}
-		if (i == N_BAUDRATES) {
+		if (i == ARRAY_SIZE(baudrate_table)) {
 			if ((flags & H_FORCE) == 0)
 				printf("## Baudrate %d bps not supported\n",
 					baudrate);
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 3c41242..e65125c 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -30,6 +30,10 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define RX_FIFO_COUNT_MASK	0xff
+#define RX_FIFO_FULL_MASK	(1 << 8)
+#define TX_FIFO_FULL_MASK	(1 << 24)
+
 static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
 {
 	u32 offset = dev_index * sizeof(struct s5p_uart);
@@ -87,8 +91,8 @@
 {
 	struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
-	/* reset and enable FIFOs, set triggers to the maximum */
-	writel(0, &uart->ufcon);
+	/* enable FIFOs */
+	writel(0x1, &uart->ufcon);
 	writel(0, &uart->umcon);
 	/* 8N1 */
 	writel(0x3, &uart->ulcon);
@@ -130,7 +134,8 @@
 	struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
 	/* wait for character to arrive */
-	while (!(readl(&uart->utrstat) & 0x1)) {
+	while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
+					 RX_FIFO_FULL_MASK))) {
 		if (serial_err_check(dev_index, 0))
 			return 0;
 	}
@@ -146,7 +151,7 @@
 	struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
 	/* wait for room in the tx FIFO */
-	while (!(readl(&uart->utrstat) & 0x2)) {
+	while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
 		if (serial_err_check(dev_index, 1))
 			return;
 	}
diff --git a/drivers/spi/cf_qspi.c b/drivers/spi/cf_qspi.c
index a37ac4e..06bcf91 100644
--- a/drivers/spi/cf_qspi.c
+++ b/drivers/spi/cf_qspi.c
@@ -171,7 +171,7 @@
 	volatile qspi_t *qspi = dev->regs;
 	u8 *txbuf = (u8 *)dout;
 	u8 *rxbuf = (u8 *)din;
-	u32 count = ((bitlen / 8) + (bitlen % 8 ? 1 : 0));
+	u32 count = DIV_ROUND_UP(bitlen, 8);
 	u32 n, i = 0;
 
 	/* Sanitize arguments */
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index 01378d0..7a25a35 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -465,6 +465,28 @@
 }
 #endif
 
+/**
+ * Set up a new SPI slave for an fdt node
+ *
+ * @param blob		Device tree blob
+ * @param node		SPI peripheral node to use
+ * @return 0 if ok, -1 on error
+ */
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
+		unsigned int cs, unsigned int max_hz, unsigned int mode)
+{
+	struct spi_bus *bus;
+	unsigned int i;
+
+	for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
+		if (bus->node == node)
+			return spi_setup_slave(i, cs, max_hz, mode);
+	}
+
+	debug("%s: Failed to find bus node %d\n", __func__, node);
+	return NULL;
+}
+
 /* Sadly there is no error return from this function */
 void spi_init(void)
 {
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index 5bed858..2ea3228 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -224,7 +224,7 @@
 	const u8 *dout, u8 *din, unsigned long flags)
 {
 	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-	int nbytes = (bitlen + 7) / 8;
+	int nbytes = DIV_ROUND_UP(bitlen, 8);
 	u32 data, cnt, i;
 	struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
 
@@ -294,7 +294,7 @@
 	/* Transfer completed, clear any pending request */
 	reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 
-	nbytes = (bitlen + 7) / 8;
+	nbytes = DIV_ROUND_UP(bitlen, 8);
 
 	cnt = nbytes % 32;
 
@@ -330,7 +330,7 @@
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 		void *din, unsigned long flags)
 {
-	int n_bytes = (bitlen + 7) / 8;
+	int n_bytes = DIV_ROUND_UP(bitlen, 8);
 	int n_bits;
 	int ret;
 	u32 blk_size;
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 60e03a4..7bb91e5 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -1105,8 +1105,7 @@
 
 	/* Configure all the endpoint FIFO's and start usb controller */
 	musbr = musb_cfg.regs;
-	musb_configure_ep(&epinfo[0],
-			sizeof(epinfo) / sizeof(struct musb_epinfo));
+	musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
 	musb_start();
 
 	/*
diff --git a/drivers/usb/musb/musb_udc.c b/drivers/usb/musb/musb_udc.c
index e0b4217..e8a2ce0 100644
--- a/drivers/usb/musb/musb_udc.c
+++ b/drivers/usb/musb/musb_udc.c
@@ -894,8 +894,7 @@
 			epinfo[id * 2].epsize = endpoint->rcv_packetSize;
 		}
 
-		musb_configure_ep(&epinfo[0],
-				  sizeof(epinfo) / sizeof(struct musb_epinfo));
+		musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
 	} else {
 		if (debug_level > 0)
 			serial_printf("ERROR : %s endpoint request %d "
diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c
index ed0823b..c3606d5 100644
--- a/drivers/video/exynos_fb.c
+++ b/drivers/video/exynos_fb.c
@@ -319,10 +319,10 @@
 #ifdef CONFIG_OF_CONTROL
 	if (exynos_fimd_parse_dt(gd->fdt_blob))
 		debug("Can't get proper panel info\n");
-#endif
+#else
 	/* initialize parameters which is specific to panel. */
 	init_panel_info(&panel_info);
-
+#endif
 	panel_width = panel_info.vl_width;
 	panel_height = panel_info.vl_height;
 
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 3e9ca11..8cfc3fa 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -82,6 +82,9 @@
 	unsigned long fdt_size;	/* Space reserved for relocated FDT */
 	void **jt;		/* jump table */
 	char env_buf[32];	/* buffer for getenv() before reloc. */
+#ifdef CONFIG_TRACE
+	void		*trace_buff;	/* The trace buffer */
+#endif
 	struct arch_global_data arch;	/* architecture-specific data */
 } gd_t;
 #endif
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4b39844..3e32eee 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -90,9 +90,6 @@
 extern ulong _rel_dyn_start_ofs;
 extern ulong _rel_dyn_end_ofs;
 
-/* Start/end of the relocation symbol table, as an offset from _start */
-extern ulong _dynsym_start_ofs;
-
 /* End of the region to be relocated, as an offset form _start */
 extern ulong _image_copy_end_ofs;
 
diff --git a/include/command.h b/include/command.h
index 65692fd..9e05ddc 100644
--- a/include/command.h
+++ b/include/command.h
@@ -110,6 +110,8 @@
 }
 #endif
 
+extern int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
 extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
 			   char *const argv[]);
 
diff --git a/include/common.h b/include/common.h
index 126891d..e5220cf 100644
--- a/include/common.h
+++ b/include/common.h
@@ -750,6 +750,10 @@
 void	irq_free_handler   (int);
 void	reset_timer	   (void);
 ulong	get_timer	   (ulong base);
+
+/* Return value of monotonic microsecond timer */
+unsigned long timer_get_us(void);
+
 void	enable_interrupts  (void);
 int	disable_interrupts (void);
 
diff --git a/include/configs/B4860QDS.h b/include/configs/B4860QDS.h
index c15bbd8..a823f9f 100644
--- a/include/configs/B4860QDS.h
+++ b/include/configs/B4860QDS.h
@@ -34,6 +34,15 @@
 #define CONFIG_RESET_VECTOR_ADDRESS	0xfffffffc
 #endif
 
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+/* Set 1M boot space */
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR (CONFIG_SYS_TEXT_BASE & 0xfff00000)
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS \
+		(0x300000000ull | CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR)
+#define CONFIG_RESET_VECTOR_ADDRESS 0xfffffffc
+#define CONFIG_SYS_NO_FLASH
+#endif
+
 /* High Level Configuration Options */
 #define CONFIG_BOOKE
 #define CONFIG_E500			/* BOOKE e500 family */
@@ -63,6 +72,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1			/* SRIO port 1 */
 #define CONFIG_SRIO2			/* SRIO port 2 */
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #endif
 
 #define CONFIG_FSL_LAW			/* Use common FSL init code */
@@ -84,14 +94,15 @@
 #define CONFIG_ENV_OVERWRITE
 
 #ifdef CONFIG_SYS_NO_FLASH
+#if !defined(CONFIG_SRIO_PCIE_BOOT_SLAVE) && !defined(CONFIG_RAMBOOT_PBL)
 #define CONFIG_ENV_IS_NOWHERE
+#endif
 #else
 #define CONFIG_FLASH_CFI_DRIVER
 #define CONFIG_SYS_FLASH_CFI
 #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
 #endif
 
-#ifndef CONFIG_SYS_NO_FLASH
 #if defined(CONFIG_SPIFLASH)
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #define CONFIG_ENV_IS_IN_SPI_FLASH
@@ -113,16 +124,18 @@
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE			CONFIG_SYS_NAND_BLOCK_SIZE
 #define CONFIG_ENV_OFFSET		(5 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+#define CONFIG_ENV_IS_IN_REMOTE
+#define CONFIG_ENV_ADDR		0xffe20000
+#define CONFIG_ENV_SIZE		0x2000
+#elif defined(CONFIG_ENV_IS_NOWHERE)
+#define CONFIG_ENV_SIZE		0x2000
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SECT_SIZE)
 #define CONFIG_ENV_SIZE		0x2000
 #define CONFIG_ENV_SECT_SIZE	0x20000 /* 128K (one sector) */
 #endif
-#else /* CONFIG_SYS_NO_FLASH */
-#define CONFIG_ENV_SIZE                0x2000
-#define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
-#endif
 
 #ifndef __ASSEMBLY__
 unsigned long get_board_sys_clk(void);
@@ -223,7 +236,7 @@
 /* NOR Flash Timing Params */
 #define CONFIG_SYS_NOR_CSOR	CSOR_NOR_ADM_SHIFT(4)
 #define CONFIG_SYS_NOR_FTIM0	(FTIM0_NOR_TACSE(0x01) | \
-				FTIM0_NOR_TEADC(0x01) | \
+				FTIM0_NOR_TEADC(0x04) | \
 				FTIM0_NOR_TEAHC(0x20))
 #define CONFIG_SYS_NOR_FTIM1	(FTIM1_NOR_TACO(0x35) | \
 				FTIM1_NOR_TRAD_NOR(0x1A) |\
@@ -600,6 +613,16 @@
 #elif defined(CONFIG_NAND)
 #define CONFIG_SYS_QE_FMAN_FW_IN_NAND
 #define CONFIG_SYS_QE_FMAN_FW_ADDR	(6 * 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
+ * in two corenet boards, slave's ucode could be stored in master's memory
+ * space, the address can be mapped from slave TLB->slave LAW->
+ * slave SRIO or PCIE outbound window->master inbound window->
+ * master LAW->the ucode address in master's memory space.
+ */
+#define CONFIG_SYS_QE_FMAN_FW_IN_REMOTE
+#define CONFIG_SYS_QE_FMAN_FW_ADDR	0xFFE00000
 #else
 #define CONFIG_SYS_QE_FMAN_FW_IN_NOR
 #define CONFIG_SYS_QE_FMAN_FW_ADDR		0xEFF40000
diff --git a/include/configs/BSC9131RDB.h b/include/configs/BSC9131RDB.h
index fd076e0..b5911c6 100644
--- a/include/configs/BSC9131RDB.h
+++ b/include/configs/BSC9131RDB.h
@@ -40,10 +40,34 @@
 #define CONFIG_RESET_VECTOR_ADDRESS	0x1107fffc
 #endif
 
-#ifndef CONFIG_SYS_MONITOR_BASE
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#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		0xFFFFE000
+#define CONFIG_SPL_MAX_SIZE		8192
+#define CONFIG_SPL_RELOC_TEXT_BASE	0x00100000
+#define CONFIG_SPL_RELOC_STACK		0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	((512 << 10) - 0x2000)
+#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"
 #endif
 
+#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
+
+
 /* High Level Configuration Options */
 #define CONFIG_BOOKE			/* BOOKE */
 #define CONFIG_E500			/* BOOKE e500 family */
@@ -55,7 +79,11 @@
 #define CONFIG_ENV_OVERWRITE
 
 #define CONFIG_DDR_CLK_FREQ	66666666 /* DDRCLK on 9131 RDB */
+#if defined(CONFIG_SYS_CLK_100)
+#define CONFIG_SYS_CLK_FREQ    100000000 /* SYSCLK for 9131 RDB */
+#else
 #define CONFIG_SYS_CLK_FREQ	66666666 /* SYSCLK for 9131 RDB */
+#endif
 
 #define CONFIG_HWCONFIG
 /*
@@ -125,16 +153,21 @@
 
 #define CONFIG_SYS_IMMR		CONFIG_SYS_CCSRBAR	/* PQII uses */
 							/* CONFIG_SYS_IMMR */
+/* DSP CCSRBAR */
+#define CONFIG_SYS_FSL_DSP_CCSRBAR	CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
+#define CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS	CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
 
 /*
  * Memory map
  *
  * 0x0000_0000	0x3FFF_FFFF	DDR			1G cacheable
  * 0x8800_0000	0x8810_0000	IFC internal SRAM		1M
+ * 0xB000_0000	0xB0FF_FFFF	DSP core M2 memory	16M
  * 0xC100_0000	0xC13F_FFFF	MAPLE-2F		4M
  * 0xC1F0_0000	0xC1F3_FFFF	PA L2 SRAM Region 0	256K
  * 0xC1F8_0000	0xC1F9_FFFF	PA L2 SRAM Region 1	128K
  * 0xFED0_0000	0xFED0_3FFF	SEC Secured RAM		16K
+ * 0xFF60_0000	0xFF6F_FFFF	DSP CCSR		1M
  * 0xFF70_0000	0xFF7F_FFFF	PA CCSR			1M
  * 0xFF80_0000	0xFFFF_FFFF	Boot Page & NAND flash buffer	8M
  *
@@ -214,6 +247,9 @@
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE	1
 #define CONFIG_SYS_NS16550_CLK		get_bus_freq(0)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_NS16550_MIN_FUNCTIONS
+#endif
 
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV	/* determine from environment */
 
@@ -295,7 +331,6 @@
 /*
  * Environment
  */
-#if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_SPIFLASH)
 #define CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_ENV_SPI_BUS	0
@@ -305,15 +340,16 @@
 #define CONFIG_ENV_OFFSET	0x100000	/* 1MB */
 #define CONFIG_ENV_SECT_SIZE	0x10000
 #define CONFIG_ENV_SIZE		0x2000
-#else
-#define CONFIG_ENV_IS_NOWHERE		/* Store ENV in memory only */
-#define CONFIG_ENV_ADDR			(CONFIG_SYS_MONITOR_BASE - 0x1000)
-#define CONFIG_ENV_SIZE			0x2000
-#endif
-#else
-#define CONFIG_ENV_IS_NOWHERE	1	/* Store ENV in memory only */
+#elif defined(CONFIG_NAND)
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_SYS_EXTRA_ENV_RELOC
+#define CONFIG_ENV_SIZE		CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_OFFSET	((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
+#define CONFIG_ENV_RANGE	(3 * CONFIG_ENV_SIZE)
+#elif defined(CONFIG_SYS_RAMBOOT)
+#define CONFIG_ENV_IS_NOWHERE	/* Store ENV in memory only */
 #define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE - 0x1000)
-#define CONFIG_ENV_SIZE		0x400
+#define CONFIG_ENV_SIZE		0x2000
 #endif
 
 #define CONFIG_LOADS_ECHO		/* echo on for serial download */
@@ -406,7 +442,9 @@
 	"fdtfile=bsc9131rdb.dtb\0"		\
 	"bdev=sda1\0"	\
 	"hwconfig=usb1:dr_mode=host,phy_type=ulpi\0"	\
-	"othbootargs=ramdisk_size=600000 \0" \
+	"bootm_size=0x37000000\0"	\
+	"othbootargs=ramdisk_size=600000 " \
+	"default_hugepagesz=256m hugepagesz=256m hugepages=1\0" \
 	"usbext2boot=setenv bootargs root=/dev/ram rw "	\
 	"console=$consoledev,$baudrate $othbootargs; "	\
 	"usb start;"			\
diff --git a/include/configs/BSC9132QDS.h b/include/configs/BSC9132QDS.h
index 9d15d0e..3aa4443 100644
--- a/include/configs/BSC9132QDS.h
+++ b/include/configs/BSC9132QDS.h
@@ -49,6 +49,27 @@
 #define CONFIG_RESET_VECTOR_ADDRESS	0x1107fffc
 #endif
 
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#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		0xFFFFE000
+#define CONFIG_SPL_MAX_SIZE		8192
+#define CONFIG_SPL_RELOC_TEXT_BASE	0x00100000
+#define CONFIG_SPL_RELOC_STACK		0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	((512 << 10) - 0x2000)
+#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"
+#endif
+
 #ifndef CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_TEXT_BASE		0x8ff80000
 #endif
@@ -57,11 +78,12 @@
 #define CONFIG_RESET_VECTOR_ADDRESS	0x8ffffffc
 #endif
 
-#ifndef CONFIG_SYS_MONITOR_BASE
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#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
 
-
 /* High Level Configuration Options */
 #define CONFIG_BOOKE			/* BOOKE */
 #define CONFIG_E500			/* BOOKE e500 family */
@@ -222,6 +244,10 @@
  * IFC Definitions
  */
 /* NOR Flash on IFC */
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_NO_FLASH
+#endif
 #define CONFIG_SYS_FLASH_BASE		0x88000000
 #define CONFIG_SYS_MAX_FLASH_SECT	1024	/* Max number of sector: 32M */
 
@@ -302,7 +328,9 @@
 
 #define CONFIG_SYS_NAND_BLOCK_SIZE	(128 * 1024)
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_FSL_QIXIS
+#endif
 #ifdef CONFIG_FSL_QIXIS
 #define CONFIG_SYS_FPGA_BASE	0xffb00000
 #define CONFIG_SYS_I2C_FPGA_ADDR	0x66
@@ -338,6 +366,22 @@
 #endif
 
 /* Set up IFC registers for boot location NOR/NAND */
+#if defined(CONFIG_NAND)
+#define CONFIG_SYS_CSPR0		CONFIG_SYS_NAND_CSPR
+#define CONFIG_SYS_AMASK0		CONFIG_SYS_NAND_AMASK
+#define CONFIG_SYS_CSOR0		CONFIG_SYS_NAND_CSOR
+#define CONFIG_SYS_CS0_FTIM0		CONFIG_SYS_NAND_FTIM0
+#define CONFIG_SYS_CS0_FTIM1		CONFIG_SYS_NAND_FTIM1
+#define CONFIG_SYS_CS0_FTIM2		CONFIG_SYS_NAND_FTIM2
+#define CONFIG_SYS_CS0_FTIM3		CONFIG_SYS_NAND_FTIM3
+#define CONFIG_SYS_CSPR1		CONFIG_SYS_NOR_CSPR
+#define CONFIG_SYS_AMASK1		CONFIG_SYS_NOR_AMASK
+#define CONFIG_SYS_CSOR1		CONFIG_SYS_NOR_CSOR
+#define CONFIG_SYS_CS1_FTIM0		CONFIG_SYS_NOR_FTIM0
+#define CONFIG_SYS_CS1_FTIM1		CONFIG_SYS_NOR_FTIM1
+#define CONFIG_SYS_CS1_FTIM2		CONFIG_SYS_NOR_FTIM2
+#define CONFIG_SYS_CS1_FTIM3		CONFIG_SYS_NOR_FTIM3
+#else
 #define CONFIG_SYS_CSPR0		CONFIG_SYS_NOR_CSPR
 #define CONFIG_SYS_AMASK0		CONFIG_SYS_NOR_AMASK
 #define CONFIG_SYS_CSOR0		CONFIG_SYS_NOR_CSOR
@@ -352,6 +396,7 @@
 #define CONFIG_SYS_CS1_FTIM1		CONFIG_SYS_NAND_FTIM1
 #define CONFIG_SYS_CS1_FTIM2		CONFIG_SYS_NAND_FTIM2
 #define CONFIG_SYS_CS1_FTIM3		CONFIG_SYS_NAND_FTIM3
+#endif
 
 #define CONFIG_BOARD_EARLY_INIT_F	/* Call board_pre_init */
 #define CONFIG_BOARD_EARLY_INIT_R
@@ -374,6 +419,9 @@
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE	1
 #define CONFIG_SYS_NS16550_CLK		get_bus_freq(0)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_NS16550_MIN_FUNCTIONS
+#endif
 
 #define CONFIG_SERIAL_MULTI	1 /* Enable both serial ports */
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV	/* determine from environment */
@@ -503,7 +551,6 @@
 /*
  * Environment
  */
-#if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_SDCARD)
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_SYS_MMC_ENV_DEV		0
@@ -517,11 +564,15 @@
 #define CONFIG_ENV_OFFSET	0x100000	/* 1MB */
 #define CONFIG_ENV_SECT_SIZE	0x10000
 #define CONFIG_ENV_SIZE		0x2000
-#else
+#elif defined(CONFIG_NAND)
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SIZE		CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_OFFSET	((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
+#define CONFIG_ENV_RANGE	(3 * CONFIG_ENV_SIZE)
+#elif defined(CONFIG_SYS_RAMBOOT)
 #define CONFIG_ENV_IS_NOWHERE		/* Store ENV in memory only */
 #define CONFIG_ENV_ADDR			(CONFIG_SYS_MONITOR_BASE - 0x1000)
 #define CONFIG_ENV_SIZE			0x2000
-#endif
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #if CONFIG_SYS_MONITOR_BASE > 0xfff80000
diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h
index 5185597..7b28a27 100644
--- a/include/configs/P1010RDB.h
+++ b/include/configs/P1010RDB.h
@@ -31,10 +31,10 @@
 #define CONFIG_PHYS_64BIT
 #endif
 
-#ifdef CONFIG_P1010RDB
 #define CONFIG_P1010
+#define CONFIG_E500			/* BOOKE e500 family */
+#include <asm/config_mpc85xx.h>
 #define CONFIG_NAND_FSL_IFC
-#endif
 
 #ifdef CONFIG_SDCARD
 #define CONFIG_RAMBOOT_SDCARD
@@ -48,15 +48,25 @@
 #define CONFIG_RESET_VECTOR_ADDRESS	0x1107fffc
 #endif
 
-#ifdef CONFIG_NAND	/* NAND Boot */
-#define CONFIG_RAMBOOT_NAND
-#define CONFIG_NAND_U_BOOT
-#define CONFIG_SYS_TEXT_BASE_SPL	0xff800000
-#ifdef CONFIG_NAND_SPL
-#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE_SPL
-#else
-#define CONFIG_SYS_TEXT_BASE		0x11001000
-#endif /* CONFIG_NAND_SPL */
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#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		0xFFFFE000
+#define CONFIG_SPL_MAX_SIZE		8192
+#define CONFIG_SPL_RELOC_TEXT_BASE	0x00100000
+#define CONFIG_SPL_RELOC_STACK		0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	((512 << 10) - 0x2000)
+#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"
 #endif
 
 
@@ -74,8 +84,10 @@
 #define CONFIG_RESET_VECTOR_ADDRESS	0xeffffffc
 #endif
 
-#ifndef CONFIG_SYS_MONITOR_BASE
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#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
 
 /* High Level Configuration Options */
@@ -242,7 +254,7 @@
 #define CONFIG_SYS_CCSRBAR_PHYS_LOW		CONFIG_SYS_CCSRBAR
 
 /* Don't relocate CCSRBAR while in NAND_SPL */
-#ifdef CONFIG_NAND_SPL
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_CCSR_DO_NOT_RELOCATE
 #endif
 
@@ -268,6 +280,10 @@
  * IFC Definitions
  */
 /* NOR Flash on IFC */
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_NO_FLASH
+#endif
+
 #define CONFIG_SYS_FLASH_BASE		0xee000000
 #define CONFIG_SYS_MAX_FLASH_SECT	256	/* 32M */
 
@@ -353,7 +369,7 @@
 #define CONFIG_SYS_NAND_DDR_LAW		11
 
 /* Set up IFC registers for boot location NOR/NAND */
-#if defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SECBOOT)
+#if defined(CONFIG_NAND) || defined(CONFIG_NAND_SECBOOT)
 #define CONFIG_SYS_CSPR0		CONFIG_SYS_NAND_CSPR
 #define CONFIG_SYS_AMASK0		CONFIG_SYS_NAND_AMASK
 #define CONFIG_SYS_CSOR0		CONFIG_SYS_NAND_CSOR
@@ -385,15 +401,6 @@
 #define CONFIG_SYS_CS1_FTIM3		CONFIG_SYS_NAND_FTIM3
 #endif
 
-/* NAND boot: 8K NAND loader config */
-#define CONFIG_SYS_NAND_SPL_SIZE	0x2000
-#define CONFIG_SYS_NAND_U_BOOT_SIZE	(512 << 10)
-#define CONFIG_SYS_NAND_U_BOOT_DST	(0x11000000 - CONFIG_SYS_NAND_SPL_SIZE)
-#define CONFIG_SYS_NAND_U_BOOT_START	0x11000000
-#define CONFIG_SYS_NAND_U_BOOT_OFFS	(0)
-#define CONFIG_SYS_NAND_U_BOOT_RELOC	0x10000
-#define CONFIG_SYS_NAND_U_BOOT_RELOC_SP	(CONFIG_SYS_NAND_U_BOOT_RELOC + 0x10000)
-
 /* CPLD on IFC */
 #define CONFIG_SYS_CPLD_BASE		0xffb00000
 
@@ -421,14 +428,20 @@
 #define CONFIG_SYS_CS3_FTIM3		0x0
 #endif	/* CONFIG_SDCARD */
 
-#if defined(CONFIG_RAMBOOT_SDCARD) || defined(CONFIG_RAMBOOT_SPIFLASH) || \
-    defined(CONFIG_RAMBOOT_NAND)
+#if defined(CONFIG_RAMBOOT_SDCARD) || defined(CONFIG_RAMBOOT_SPIFLASH)
 #define CONFIG_SYS_RAMBOOT
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #else
 #undef CONFIG_SYS_RAMBOOT
 #endif
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+#if !defined(CONFIG_SPL) && !defined(CONFIG_SYS_RAMBOOT)\
+	&& !defined(CONFIG_SECURE_BOOT)
+#define CONFIG_A003399_NOR_WORKAROUND
+#endif
+#endif
+
 #define CONFIG_BOARD_EARLY_INIT_F	/* Call board_pre_init */
 #define CONFIG_BOARD_EARLY_INIT_R
 
@@ -450,7 +463,7 @@
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE	1
 #define CONFIG_SYS_NS16550_CLK		get_bus_freq(0)
-#ifdef CONFIG_NAND_SPL
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_NS16550_MIN_FUNCTIONS
 #endif
 
@@ -505,7 +518,7 @@
  * SPI interface will not be available in case of NAND boot SPI CS0 will be
  * used for SLIC
  */
-#if !defined(CONFIG_NAND_U_BOOT) || !defined(CONFIG_NAND_SECBOOT)
+#if !defined(CONFIG_NAND) || !defined(CONFIG_NAND_SECBOOT)
 /* eSPI - Enhanced SPI */
 #define CONFIG_FSL_ESPI
 #define CONFIG_SPI_FLASH
@@ -600,7 +613,6 @@
 /*
  * Environment
  */
-#if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_SDCARD)
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_FSL_FIXED_MMC_LOCATION
@@ -615,16 +627,15 @@
 #define CONFIG_ENV_OFFSET	0x100000	/* 1MB */
 #define CONFIG_ENV_SECT_SIZE	0x10000
 #define CONFIG_ENV_SIZE		0x2000
-#elif defined(CONFIG_NAND_U_BOOT)
+#elif defined(CONFIG_NAND)
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE		CONFIG_SYS_NAND_BLOCK_SIZE
-#define CONFIG_ENV_OFFSET	CONFIG_SYS_NAND_U_BOOT_SIZE
+#define CONFIG_ENV_OFFSET	((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
 #define CONFIG_ENV_RANGE	(3 * CONFIG_ENV_SIZE)
-#else
+#elif defined(CONFIG_SYS_RAMBOOT)
 #define CONFIG_ENV_IS_NOWHERE		/* Store ENV in memory only */
 #define CONFIG_ENV_ADDR			(CONFIG_SYS_MONITOR_BASE - 0x1000)
 #define CONFIG_ENV_SIZE			0x2000
-#endif
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #if CONFIG_SYS_MONITOR_BASE > 0xfff80000
diff --git a/include/configs/P1023RDB.h b/include/configs/P1023RDB.h
new file mode 100644
index 0000000..fee8040
--- /dev/null
+++ b/include/configs/P1023RDB.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Authors:  Roy Zang <tie-fei.zang@freescale.com>
+ *	     Chunhe Lan <Chunhe.Lan@freescale.com>
+ *
+ * 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
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifndef CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_TEXT_BASE	0xeff80000
+#endif
+
+#ifndef CONFIG_SYS_MONITOR_BASE
+#define CONFIG_SYS_MONITOR_BASE	CONFIG_SYS_TEXT_BASE	/* start of monitor */
+#endif
+
+#ifndef CONFIG_RESET_VECTOR_ADDRESS
+#define CONFIG_RESET_VECTOR_ADDRESS	0xeffffffc
+#endif
+
+/* High Level Configuration Options */
+#define CONFIG_BOOKE		/* BOOKE */
+#define CONFIG_E500		/* BOOKE e500 family */
+#define CONFIG_MPC85xx
+#define CONFIG_P1023
+#define CONFIG_MP		/* support multiple processors */
+
+#define CONFIG_FSL_ELBC		/* Has Enhanced localbus controller */
+#define CONFIG_PCI		/* Enable PCI/PCIE */
+#define CONFIG_PCI_INDIRECT_BRIDGE     /* indirect PCI bridge support */
+#define CONFIG_PCIE1		/* PCIE controler 1 (slot 1) */
+#define CONFIG_PCIE2		/* PCIE controler 2 (slot 2) */
+#define CONFIG_PCIE3		/* PCIE controler 3 (slot 3) */
+#define CONFIG_FSL_PCI_INIT	/* Use common FSL init code */
+#define CONFIG_FSL_PCIE_RESET	/* need PCIe reset errata */
+#define CONFIG_SYS_PCI_64BIT	/* enable 64-bit PCI resources */
+#define CONFIG_FSL_LAW		/* Use common FSL init code */
+
+#ifndef __ASSEMBLY__
+extern unsigned long get_clock_freq(void);
+#endif
+
+#define CONFIG_SYS_CLK_FREQ	66666666
+#define CONFIG_DDR_CLK_FREQ	CONFIG_SYS_CLK_FREQ
+
+/*
+ * These can be toggled for performance analysis, otherwise use default.
+ */
+#define CONFIG_L2_CACHE			/* toggle L2 cache */
+#define CONFIG_BTB			/* toggle branch predition */
+#define CONFIG_HWCONFIG
+
+#define CONFIG_ENABLE_36BIT_PHYS
+
+#define CONFIG_SYS_MEMTEST_START	0x01000000	/* memtest works on */
+#define CONFIG_SYS_MEMTEST_END		0x02000000
+
+#define CONFIG_PANIC_HANG	/* do not reset board on panic */
+
+/* Implement conversion of addresses in the LBC */
+#define CONFIG_SYS_LBC_LBCR		0x00000000
+#define CONFIG_SYS_LBC_LCRR		LCRR_CLKDIV_8
+
+/* DDR Setup */
+#define CONFIG_VERY_BIG_RAM
+#define CONFIG_SYS_DDR_SDRAM_BASE	0x00000000
+#define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_DDR_SDRAM_BASE
+
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+#define CONFIG_CHIP_SELECTS_PER_CTRL	1
+
+#define CONFIG_DDR_SPD
+#define CONFIG_FSL_DDR3
+#define CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SYS_SDRAM_SIZE		512u	/* DDR is 512M */
+#define CONFIG_SYS_SPD_BUS_NUM          0
+#define SPD_EEPROM_ADDRESS              0x50
+#define CONFIG_SYS_DDR_RAW_TIMING
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000	0x1fff_ffff	DDR			512M cacheable
+ * 0x8000_0000	0xbfff_ffff	PCI Express Mem		1G non-cacheable
+ * 0xc000_0000	0xdfff_ffff	PCI			512M non-cacheable
+ * 0xe100_0000	0xe3ff_ffff	PCI IO range		4M non-cacheable
+ * 0xff00_0000	0xff3f_ffff	DPAA_QBMAN		4M cacheable
+ * 0xff60_0000	0xff7f_ffff	CCSR			2M non-cacheable
+ * 0xffd0_0000	0xffd0_3fff	L1 for stack		16K cacheable TLB0
+ *
+ * Localbus non-cacheable
+ *
+ * 0xec00_0000	0xefff_ffff	NOR flash		64M non-cacheable
+ * 0xffa0_0000	0xffaf_ffff	NAND			1M non-cacheable
+ */
+
+/*
+ * Local Bus Definitions
+ */
+#define CONFIG_SYS_FLASH_BASE		0xec000000 /* start of FLASH 64M */
+#define CONFIG_SYS_FLASH_BASE_PHYS	CONFIG_SYS_FLASH_BASE
+
+#define CONFIG_FLASH_BR_PRELIM  (BR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) \
+				| BR_PS_16 | BR_V)
+#define CONFIG_FLASH_OR_PRELIM	0xfc000ff7
+
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* number of banks */
+#define CONFIG_SYS_MAX_FLASH_SECT	512	/* sectors per device */
+#define CONFIG_SYS_FLASH_ERASE_TOUT	60000	/* Flash Erase Timeout (ms) */
+#define CONFIG_SYS_FLASH_WRITE_TOUT	500	/* Flash Write Timeout (ms) */
+
+#define CONFIG_BOARD_EARLY_INIT_F	/* call board_early_init_f function */
+#define CONFIG_BOARD_EARLY_INIT_R	/* call board_early_init_r function */
+
+#define CONFIG_SYS_INIT_RAM_LOCK
+#define CONFIG_SYS_INIT_RAM_ADDR	0xffd00000	/* Initial L1 address */
+#define CONFIG_SYS_INIT_RAM_SIZE	0x00004000/* Size of used area in RAM */
+#define CONFIG_SYS_GBL_DATA_OFFSET	(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)	  /* Reserve 512 kB for Mon */
+#define CONFIG_SYS_MALLOC_LEN	(6 * 1024 * 1024) /* Reserved for malloc */
+
+#define CONFIG_SYS_NAND_BASE		0xffa00000
+#define CONFIG_SYS_NAND_BASE_PHYS	CONFIG_SYS_NAND_BASE
+
+#define CONFIG_SYS_NAND_BASE_LIST	{ CONFIG_SYS_NAND_BASE }
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_MTD_NAND_VERIFY_WRITE
+#define CONFIG_CMD_NAND
+#define CONFIG_NAND_FSL_ELBC
+#define CONFIG_SYS_NAND_BLOCK_SIZE	(128 * 1024)
+
+/* NAND flash config */
+#define CONFIG_SYS_NAND_BR_PRELIM  (BR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \
+				| (2<<BR_DECC_SHIFT)	/* Use HW ECC */ \
+				| BR_PS_8		/* Port Size = 8bit */ \
+				| BR_MS_FCM		/* MSEL = FCM */ \
+				| BR_V)			/* valid */
+#define CONFIG_SYS_NAND_OR_PRELIM  (OR_AM_256KB		/* length 256K */ \
+				| OR_FCM_PGS \
+				| OR_FCM_CSCT \
+				| OR_FCM_CST \
+				| OR_FCM_CHT \
+				| OR_FCM_SCY_1 \
+				| OR_FCM_TRLX \
+				| OR_FCM_EHTR)
+
+#define CONFIG_SYS_BR0_PRELIM	CONFIG_FLASH_BR_PRELIM	/* NOR Base Address */
+#define CONFIG_SYS_OR0_PRELIM	CONFIG_FLASH_OR_PRELIM	/* NOR Options */
+#define CONFIG_SYS_BR1_PRELIM	CONFIG_SYS_NAND_BR_PRELIM
+#define CONFIG_SYS_OR1_PRELIM	CONFIG_SYS_NAND_OR_PRELIM /* NAND Options */
+
+/* Serial Port */
+#define CONFIG_CONS_INDEX		1
+#undef	CONFIG_SERIAL_SOFTWARE_FIFO
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	1
+#define CONFIG_SYS_NS16550_CLK		get_bus_freq(0)
+
+#define CONFIG_SYS_BAUDRATE_TABLE	\
+	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200}
+
+#define CONFIG_SYS_NS16550_COM1	(CONFIG_SYS_CCSRBAR + 0x4500)
+#define CONFIG_SYS_NS16550_COM2	(CONFIG_SYS_CCSRBAR + 0x4600)
+
+/* Use the HUSH parser */
+#define CONFIG_SYS_HUSH_PARSER
+
+/*
+ * Pass open firmware flat tree
+ */
+#define CONFIG_OF_LIBFDT
+#define CONFIG_OF_BOARD_SETUP
+#define CONFIG_OF_STDOUT_VIA_ALIAS
+
+/* new uImage format support */
+#define CONFIG_FIT
+#define CONFIG_FIT_VERBOSE	/* enable fit_format_{error,warning}() */
+
+/* I2C */
+#define CONFIG_FSL_I2C		/* Use FSL common I2C driver */
+#define CONFIG_HARD_I2C		/* I2C with hardware support */
+#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_SYS_I2C_SPEED	400000	/* I2C speed and slave address */
+#define CONFIG_SYS_I2C_SLAVE		0x7F
+#define CONFIG_SYS_I2C_OFFSET		0x3000
+#define CONFIG_SYS_I2C2_OFFSET		0x3100
+
+/*
+ * I2C2 EEPROM
+ */
+#define CONFIG_ID_EEPROM
+#ifdef CONFIG_ID_EEPROM
+#define CONFIG_SYS_I2C_EEPROM_NXID
+#endif
+#define CONFIG_SYS_I2C_EEPROM_ADDR		0x50
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		1
+#define CONFIG_SYS_EEPROM_BUS_NUM		0
+
+#define CONFIG_CMD_I2C
+
+/*
+ * General PCI
+ * Memory space is mapped 1-1, but I/O space must start from 0.
+ */
+
+/* controller 3, Slot 1, tgtid 3, Base address b000 */
+#define CONFIG_SYS_PCIE3_NAME		"Slot 3"
+#define CONFIG_SYS_PCIE3_MEM_VIRT	0x80000000
+#define CONFIG_SYS_PCIE3_MEM_BUS	0x80000000
+#define CONFIG_SYS_PCIE3_MEM_PHYS	0x80000000
+#define CONFIG_SYS_PCIE3_MEM_SIZE	0x20000000	/* 512M */
+#define CONFIG_SYS_PCIE3_IO_VIRT	0xffc00000
+#define CONFIG_SYS_PCIE3_IO_BUS		0x00000000
+#define CONFIG_SYS_PCIE3_IO_PHYS	0xffc00000
+#define CONFIG_SYS_PCIE3_IO_SIZE	0x00010000	/* 64k */
+
+/* controller 2, direct to uli, tgtid 2, Base address 9000 */
+#define CONFIG_SYS_PCIE2_NAME		"Slot 2"
+#define CONFIG_SYS_PCIE2_MEM_VIRT	0xa0000000
+#define CONFIG_SYS_PCIE2_MEM_BUS	0xa0000000
+#define CONFIG_SYS_PCIE2_MEM_PHYS	0xa0000000
+#define CONFIG_SYS_PCIE2_MEM_SIZE	0x20000000	/* 512M */
+#define CONFIG_SYS_PCIE2_IO_VIRT	0xffc10000
+#define CONFIG_SYS_PCIE2_IO_BUS		0x00000000
+#define CONFIG_SYS_PCIE2_IO_PHYS	0xffc10000
+#define CONFIG_SYS_PCIE2_IO_SIZE	0x00010000	/* 64k */
+
+/* controller 1, Slot 2, tgtid 1, Base address a000 */
+#define CONFIG_SYS_PCIE1_NAME		"Slot 1"
+#define CONFIG_SYS_PCIE1_MEM_VIRT	0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_BUS	0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_PHYS	0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_SIZE	0x20000000	/* 512M */
+#define CONFIG_SYS_PCIE1_IO_VIRT	0xffc20000
+#define CONFIG_SYS_PCIE1_IO_BUS		0x00000000
+#define CONFIG_SYS_PCIE1_IO_PHYS	0xffc20000
+#define CONFIG_SYS_PCIE1_IO_SIZE	0x00010000	/* 64k */
+
+#if defined(CONFIG_PCI)
+#define CONFIG_E1000		/* Defind e1000 pci Ethernet card */
+#define CONFIG_PCI_PNP		/* do pci plug-and-play */
+#define CONFIG_PCI_SCAN_SHOW	/* show pci devices on startup */
+#endif	/* CONFIG_PCI */
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_ENV_IS_IN_FLASH
+#if CONFIG_SYS_MONITOR_BASE > 0xfff80000
+#define CONFIG_ENV_ADDR		0xfff80000
+#else
+#define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SECT_SIZE)
+#endif
+#define CONFIG_ENV_SIZE		0x2000
+#define CONFIG_ENV_SECT_SIZE	0x20000 /* 128K (one sector) */
+
+#define CONFIG_LOADS_ECHO		/* echo on for serial download */
+#define CONFIG_SYS_LOADS_BAUD_CHANGE	/* allow baudrate change */
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_IRQ
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_SETEXPR
+#define CONFIG_CMD_REGINFO
+
+#if defined(CONFIG_PCI)
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_NET
+#endif
+
+/*
+ * USB
+ */
+#define CONFIG_HAS_FSL_DR_USB
+#ifdef CONFIG_HAS_FSL_DR_USB
+#define CONFIG_USB_EHCI
+
+#ifdef CONFIG_USB_EHCI
+#define CONFIG_CMD_USB
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+#define CONFIG_USB_EHCI_FSL
+#define CONFIG_USB_STORAGE
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+#endif
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP			/* undef to save memory	*/
+#define CONFIG_CMDLINE_EDITING		/* Command-line editing */
+#define CONFIG_SYS_LOAD_ADDR	0x2000000	/* default load address */
+#define CONFIG_SYS_PROMPT	"=> "		/* Monitor Command Prompt */
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_SYS_CBSIZE	1024		/* Console I/O Buffer Size */
+#else
+#define CONFIG_SYS_CBSIZE	256		/* Console I/O Buffer Size */
+#endif
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT)+16)
+#define CONFIG_SYS_MAXARGS	16		/* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_HZ	1000		/* decrementer freq: 1ms ticks */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 64 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_SYS_BOOTMAPSZ	(64 << 20)   /* Initial Memory map for Linux*/
+#define CONFIG_SYS_BOOTM_LEN	(64 << 20)   /* Increase max gunzip size */
+
+/*
+ * Environment Configuration
+ */
+#define CONFIG_BOOTFILE		"uImage"
+#define CONFIG_UBOOTPATH	(u-boot.bin) /* U-Boot image on TFTP server */
+
+/* default location for tftp and bootm */
+#define CONFIG_LOADADDR		1000000
+
+#define CONFIG_BOOTDELAY -1	/* -1 disables auto-boot */
+
+#define CONFIG_BAUDRATE	115200
+
+/* Qman/Bman */
+#define CONFIG_SYS_DPAA_QBMAN		/* support Q/Bman */
+#define CONFIG_SYS_QMAN_MEM_BASE	0xff000000
+#define CONFIG_SYS_QMAN_MEM_PHYS	CONFIG_SYS_QMAN_MEM_BASE
+#define CONFIG_SYS_QMAN_MEM_SIZE	0x00200000
+#define CONFIG_SYS_BMAN_MEM_BASE	0xff200000
+#define CONFIG_SYS_BMAN_MEM_PHYS	CONFIG_SYS_BMAN_MEM_BASE
+#define CONFIG_SYS_BMAN_MEM_SIZE	0x00200000
+
+/* For FM */
+#define CONFIG_SYS_DPAA_FMAN
+#define CONFIG_PHY_GIGE		/* Include GbE speed/duplex detection */
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+#define CONFIG_FMAN_ENET
+#define CONFIG_PHY_ATHEROS
+#endif
+
+/* Default address of microcode for the Linux Fman driver */
+/* QE microcode/firmware address */
+#define CONFIG_SYS_QE_FMAN_FW_IN_NOR
+#define CONFIG_SYS_QE_FMAN_FW_ADDR	0xeff40000
+#define CONFIG_SYS_QE_FMAN_FW_LENGTH	0x10000
+#define CONFIG_SYS_FDT_PAD		(0x3000 + CONFIG_SYS_QE_FMAN_FW_LENGTH)
+
+#ifdef CONFIG_FMAN_ENET
+#define CONFIG_SYS_FM1_DTSEC1_PHY_ADDR	0x1
+#define CONFIG_SYS_FM1_DTSEC2_PHY_ADDR	0x2
+
+#define CONFIG_SYS_TBIPA_VALUE	8
+#define CONFIG_MII		/* MII PHY management */
+#define CONFIG_ETHPRIME		"FM1@DTSEC1"
+#endif
+
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+	"hwconfig=usb1:dr_mode=host,phy_type=ulpi\0"
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/P2041RDB.h b/include/configs/P2041RDB.h
index 9cd3a7c..4ea8717 100644
--- a/include/configs/P2041RDB.h
+++ b/include/configs/P2041RDB.h
@@ -77,6 +77,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1			/* SRIO port 1 */
 #define CONFIG_SRIO2			/* SRIO port 2 */
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_DPAA_RMAN		/* RMan */
 
 #define CONFIG_FSL_LAW			/* Use common FSL init code */
diff --git a/include/configs/P3041DS.h b/include/configs/P3041DS.h
index ce8f9b0..dd2b9c3 100644
--- a/include/configs/P3041DS.h
+++ b/include/configs/P3041DS.h
@@ -40,7 +40,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1			/* SRIO port 1 */
 #define CONFIG_SRIO2			/* SRIO port 2 */
-
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_ICS307_REFCLK_HZ		25000000  /* ICS307 ref clk freq */
 
 #include "corenet_ds.h"
diff --git a/include/configs/P4080DS.h b/include/configs/P4080DS.h
index 53979dd..48acee4 100644
--- a/include/configs/P4080DS.h
+++ b/include/configs/P4080DS.h
@@ -36,7 +36,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1			/* SRIO port 1 */
 #define CONFIG_SRIO2			/* SRIO port 2 */
-
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_ICS307_REFCLK_HZ		33333000  /* ICS307 ref clk freq */
 
 #include "corenet_ds.h"
diff --git a/include/configs/P5020DS.h b/include/configs/P5020DS.h
index 778230d..d1e27c4 100644
--- a/include/configs/P5020DS.h
+++ b/include/configs/P5020DS.h
@@ -41,7 +41,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1			/* SRIO port 1 */
 #define CONFIG_SRIO2			/* SRIO port 2 */
-
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_ICS307_REFCLK_HZ		25000000  /* ICS307 ref clk freq */
 
 #include "corenet_ds.h"
diff --git a/include/configs/a3m071.h b/include/configs/a3m071.h
index e9af825..8f29229 100644
--- a/include/configs/a3m071.h
+++ b/include/configs/a3m071.h
@@ -426,6 +426,7 @@
 #define CONFIG_SPL_BSS_MAX_SIZE		(64 << 10)
 
 #define CONFIG_SPL_OS_BOOT
+#define CONFIG_SPL_ENV_SUPPORT
 /* Place patched DT blob (fdt) at this address */
 #define CONFIG_SYS_SPL_ARGS_ADDR	0x01800000
 
diff --git a/include/configs/ac14xx.h b/include/configs/ac14xx.h
index 7cb10fb..381bcdd 100644
--- a/include/configs/ac14xx.h
+++ b/include/configs/ac14xx.h
@@ -72,7 +72,7 @@
 #define CONFIG_SYS_MAX_RAM_SIZE		0x20000000
 
 /*
- * DDR Controller Configuration XXX TODO
+ * DDR Controller Configuration
  *
  * SYS_CFG:
  *	[31:31]	MDDRC Soft Reset:	Diabled
@@ -265,7 +265,6 @@
 
 /*
  * CS related parameters
- * TODO document these
  */
 /* CS0 Flash */
 #define CONFIG_SYS_CS0_CFG		0x00031110
@@ -331,8 +330,6 @@
 #endif
 
 #define CONFIG_BAUDRATE			115200	/* ... at 115200 bps */
-#define CONFIG_SYS_BAUDRATE_TABLE  \
-	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 115200}
 
 #define CONSOLE_FIFO_TX_SIZE		FIFOC_PSC3_TX_SIZE
 #define CONSOLE_FIFO_TX_ADDR		FIFOC_PSC3_TX_ADDR
@@ -497,30 +494,26 @@
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_TIMESTAMP
 
-#define CONFIG_HOSTNAME		ac14xx
-#define CONFIG_BOOTFILE		"ac14xx/uImage"
-#define CONFIG_ROOTPATH		"/opt/eldk/ppc_6xx"
-
 /* default load addr for tftp and bootm */
 #define CONFIG_LOADADDR		400000
 
 #define CONFIG_BOOTDELAY	2	/* -1 disables auto-boot */
 
-/* XXX TODO need to specify the builtin environment */
+/* the builtin environment and standard greeting */
 #define CONFIG_PREBOOT	"echo;"	\
 	"echo Type \\\"run flash_nfs\\\" to mount root filesystem over NFS;" \
 	"echo"
 
 #define CONFIG_EXTRA_ENV_SETTINGS_DEVEL					\
-	"muster_nr=00\0"						\
+	"muster_nr=-00\0"						\
 	"fromram=run ramargs addip addtty; "				\
-		"tftp ${fdt_addr_r} k6m2/ac14xx.dtb-${muster_nr}; "	\
-		"tftp ${kernel_addr_r} k6m2/uImage-${muster_nr}; "	\
-		"tftp ${ramdisk_addr_r} k6m2/uFS-${muster_nr}; "	\
+		"tftp ${fdt_addr_r} ac14xx/ac14xx.dtb${muster_nr}; "	\
+		"tftp ${kernel_addr_r} ac14xx/uImage${muster_nr}; "	\
+		"tftp ${ramdisk_addr_r} ac14xx/uFS${muster_nr}; "	\
 		"bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}\0" \
 	"fromnfs=run nfsargs addip addtty; "				\
-		"tftp ${fdt_addr_r} k6m2/ac14xx.dtb-${muster_nr}; "	\
-		"tftp ${kernel_addr_r} k6m2/uImage-${muster_nr}; "	\
+		"tftp ${fdt_addr_r} ac14xx/ac14xx.dtb${muster_nr}; "	\
+		"tftp ${kernel_addr_r} ac14xx/uImage${muster_nr}; "	\
 		"bootm ${kernel_addr_r} - ${fdt_addr_r}\0"		\
 	"fromflash=run nfsargs addip addtty; "				\
 		"bootm fc020000 - fc000000\0"				\
@@ -548,12 +541,11 @@
 	"u-boot=ac14xx/u-boot.bin\0"					\
 	"bootfile=ac14xx/uImage\0"					\
 	"fdtfile=ac14xx/ac14xx.dtb\0"					\
-	"rootpath=/opt/eldk/ppc_6xx\n"					\
 	"netdev=eth0\0"							\
 	"consdev=ttyPSC0\0"						\
 	"hostname=ac14xx\0"						\
 	"nfsargs=setenv bootargs root=/dev/nfs rw "			\
-		"nfsroot=${serverip}:${rootpath}-${muster_nr}\0"	\
+		"nfsroot=${serverip}:${rootpath}${muster_nr}\0"	\
 	"ramargs=setenv bootargs root=/dev/ram rw\0"			\
 	"addip=setenv bootargs ${bootargs} "				\
 		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\
@@ -583,6 +575,8 @@
 
 #define CONFIG_BOOTCOMMAND	"run production"
 
+#define CONFIG_ARP_TIMEOUT	200UL
+
 #define CONFIG_FIT		1
 #define CONFIG_OF_LIBFDT	1
 #define CONFIG_OF_BOARD_SETUP	1
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 737e19e..c5a6d4b 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -60,7 +60,7 @@
 	"rdaddr=0x81000000\0" \
 	"bootdir=/boot\0" \
 	"bootfile=uImage\0" \
-	"fdtfile=\0" \
+	"fdtfile=undefined\0" \
 	"console=ttyO0,115200n8\0" \
 	"optargs=\0" \
 	"mtdids=" MTDIDS_DEFAULT "\0" \
@@ -145,8 +145,9 @@
 		"if test $board_name = A33515BB; then " \
 			"setenv fdtfile am335x-evm.dtb; fi; " \
 		"if test $board_name = A335X_SK; then " \
-			"setenv fdtfile am335x-evmsk.dtb; fi\0" \
-
+			"setenv fdtfile am335x-evmsk.dtb; fi; " \
+		"if test $fdtfile = undefined; then " \
+			"echo WARNING: Could not determine device tree to use; fi; \0"
 #endif
 
 #define CONFIG_BOOTCOMMAND \
@@ -355,6 +356,7 @@
 #define CONFIG_SPL_GPIO_SUPPORT
 #define CONFIG_SPL_YMODEM_SUPPORT
 #define CONFIG_SPL_NET_SUPPORT
+#define CONFIG_SPL_ENV_SUPPORT
 #define CONFIG_SPL_NET_VCI_STRING	"AM335x U-Boot SPL"
 #define CONFIG_SPL_ETH_SUPPORT
 #define CONFIG_SPL_SPI_SUPPORT
diff --git a/include/configs/at91sam9n12ek.h b/include/configs/at91sam9n12ek.h
index 8d2673d..b4b1c31 100644
--- a/include/configs/at91sam9n12ek.h
+++ b/include/configs/at91sam9n12ek.h
@@ -167,6 +167,10 @@
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Ethernet */
+#define CONFIG_KS8851_MLL
+#define CONFIG_KS8851_MLL_BASEADDR	0x30000000 /* use NCS2 */
+
 #define CONFIG_SYS_LOAD_ADDR		0x22000000 /* load address */
 
 #define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index 2fefdc8..288ef8d 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -168,6 +168,13 @@
  */
 #include <config_cmd_default.h>
 
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE	(16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR		0x01400000
+
 #define CONFIG_CMD_BDI
 #define CONFIG_CMD_BOOTD
 #define CONFIG_CMD_CONSOLE
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 0eea28c..c11f005 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -41,4 +41,7 @@
 #define CONFIG_BAUDRATE			115200
 
 #define CONFIG_SYS_OMAP_ABE_SYSCK
+
+#define CONSOLEDEV		"ttyO0"
+
 #endif /* __CONFIG_DRA7XX_EVM_H */
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
index 41d6cf9..e2a096b 100644
--- a/include/configs/exynos5250-dt.h
+++ b/include/configs/exynos5250-dt.h
@@ -43,6 +43,14 @@
 #define CONFIG_OF_CONTROL
 #define CONFIG_OF_SEPARATE
 
+/* Allow tracing to be enabled */
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE	(16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR		0x50000000
+
 /* Keep L2 Cache Disabled */
 #define CONFIG_SYS_DCACHE_OFF
 
@@ -82,24 +90,34 @@
 #define CONFIG_BAUDRATE			115200
 #define EXYNOS5_DEFAULT_UART_OFFSET	0x010000
 
+/* Enable keyboard */
+#define CONFIG_CROS_EC		/* CROS_EC protocol */
+#define CONFIG_CROS_EC_SPI		/* Support CROS_EC over SPI */
+#define CONFIG_CROS_EC_I2C		/* Support CROS_EC over I2C */
+#define CONFIG_CROS_EC_KEYB	/* CROS_EC keyboard input */
+#define CONFIG_CMD_CROS_EC
+#define CONFIG_KEYBOARD
+
 /* Console configuration */
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 #define EXYNOS_DEVICE_SETTINGS \
-		"stdin=serial\0" \
+		"stdin=serial,cros-ec-keyb\0" \
 		"stdout=serial,lcd\0" \
 		"stderr=serial,lcd\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	EXYNOS_DEVICE_SETTINGS
 
-#define TZPC_BASE_OFFSET		0x10000
-
 /* SD/MMC configuration */
 #define CONFIG_GENERIC_MMC
 #define CONFIG_MMC
 #define CONFIG_SDHCI
 #define CONFIG_S5P_SDHCI
+#define CONFIG_DWMMC
+#define CONFIG_EXYNOS_DWMMC
+#define CONFIG_SUPPORT_EMMC_BOOT
+
 
 #define CONFIG_BOARD_EARLY_INIT_F
 
@@ -232,6 +250,10 @@
 #define SPI_FLASH_UBOOT_POS		(CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)
 
 #define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
 
 #define CONFIG_IRAM_STACK	0x02050000
 
@@ -262,6 +284,7 @@
 #define CONFIG_CMD_SF
 #define CONFIG_CMD_SPI
 #define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SPI_FLASH_GIGADEVICE
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 #define CONFIG_SF_DEFAULT_SPEED		50000000
 #define EXYNOS5_SPI_NUM_CONTROLLERS	5
diff --git a/include/configs/lacie_kw.h b/include/configs/lacie_kw.h
index 09b5798..e2b3b21 100644
--- a/include/configs/lacie_kw.h
+++ b/include/configs/lacie_kw.h
@@ -120,10 +120,14 @@
 #endif
 
 /*
+ * Enable platform initialisation via misc_init_r() function
+ */
+#define CONFIG_MISC_INIT_R
+
+/*
  * Ethernet Driver configuration
  */
 #ifdef CONFIG_CMD_NET
-#define CONFIG_MISC_INIT_R /* Call misc_init_r() to initialize MAC address */
 #define CONFIG_MVGBE_PORTS		{1, 0} /* enable port 0 only */
 #define CONFIG_NETCONSOLE
 #endif
@@ -153,6 +157,9 @@
 #define CONFIG_SYS_I2C_EEPROM_ADDR		0x50
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS	4 /* 16-byte page size */
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		1 /* 8-bit device address */
+#if defined(CONFIG_NET2BIG_V2)
+#define CONFIG_SYS_I2C_G762_ADDR		0x3e
+#endif
 #endif /* CONFIG_CMD_I2C */
 
 /*
diff --git a/include/configs/omap4_common.h b/include/configs/omap4_common.h
index 3e5d36b..2fa4382 100644
--- a/include/configs/omap4_common.h
+++ b/include/configs/omap4_common.h
@@ -150,6 +150,7 @@
 	"console=ttyO2,115200n8\0" \
 	"fdt_high=0xffffffff\0" \
 	"fdtaddr=0x80f80000\0" \
+	"fdtfile=undefined\0" \
 	"bootpart=0:2\0" \
 	"bootdir=/boot\0" \
 	"bootfile=zImage\0" \
@@ -177,8 +178,12 @@
 			"setenv fdtfile omap4-sdp.dtb; fi; " \
 		"if test $board_name = panda; then " \
 			"setenv fdtfile omap4-panda.dtb; fi;" \
+		"if test $board_name = panda-a4; then " \
+			"setenv fdtfile omap4-panda-a4.dtb; fi;" \
 		"if test $board_name = panda-es; then " \
-			"setenv fdtfile omap4-panda-es.dtb; fi; \0" \
+			"setenv fdtfile omap4-panda-es.dtb; fi;" \
+		"if test $fdtfile = undefined; then " \
+			"echo WARNING: Could not determine device tree to use; fi; \0" \
 	"loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \
 
 #define CONFIG_BOOTCOMMAND \
diff --git a/include/configs/omap5_common.h b/include/configs/omap5_common.h
index ddf2ad4..b87ee42 100644
--- a/include/configs/omap5_common.h
+++ b/include/configs/omap5_common.h
@@ -136,9 +136,10 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"loadaddr=0x82000000\0" \
-	"console=ttyO2,115200n8\0" \
+	"console=" CONSOLEDEV ",115200n8\0" \
 	"fdt_high=0xffffffff\0" \
 	"fdtaddr=0x80f80000\0" \
+	"fdtfile=undefined\0" \
 	"bootpart=0:2\0" \
 	"bootdir=/boot\0" \
 	"bootfile=zImage\0" \
@@ -166,7 +167,11 @@
 		"bootz ${loadaddr} - ${fdtaddr}\0" \
 	"findfdt="\
 		"if test $board_name = omap5_uevm; then " \
-			"setenv fdtfile omap5-uevm.dtb; fi;\0 " \
+			"setenv fdtfile omap5-uevm.dtb; fi; " \
+		"if test $board_name = dra7xx; then " \
+			"setenv fdtfile dra7-evm.dtb; fi;" \
+		"if test $fdtfile = undefined; then " \
+			"echo WARNING: Could not determine device tree to use; fi; \0" \
 	"loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile};\0" \
 
 #define CONFIG_BOOTCOMMAND \
diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h
index dea05bc..46dacc2 100644
--- a/include/configs/omap5_uevm.h
+++ b/include/configs/omap5_uevm.h
@@ -53,7 +53,9 @@
 #define CONFIG_PARTITION_UUIDS
 #define CONFIG_CMD_PART
 
-#define CONFIG_SYS_PROMPT		"OMAP5430 EVM # "
+#define CONFIG_SYS_PROMPT		"OMAP5432 uEVM # "
+
+#define CONSOLEDEV		"ttyO2"
 
 #define CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC	16296
 #endif /* __CONFIG_OMAP5_EVM_H */
diff --git a/include/configs/origen.h b/include/configs/origen.h
index ff2b24d..e179911 100644
--- a/include/configs/origen.h
+++ b/include/configs/origen.h
@@ -96,6 +96,8 @@
 #define CONFIG_SPL
 #define COPY_BL2_FNPTR_ADDR	0x02020030
 
+#define CONFIG_SPL_TEXT_BASE	0x02021410
+
 #define CONFIG_BOOTCOMMAND	"fatload mmc 0 40007000 uImage; bootm 40007000"
 
 /* Miscellaneous configurable options */
diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h
index 2ecd105..9b16c47 100644
--- a/include/configs/pcm051.h
+++ b/include/configs/pcm051.h
@@ -231,6 +231,7 @@
 #define CONFIG_SPL_GPIO_SUPPORT
 #define CONFIG_SPL_YMODEM_SUPPORT
 #define CONFIG_SPL_NET_SUPPORT
+#define CONFIG_SPL_ENV_SUPPORT
 #define CONFIG_SPL_NET_VCI_STRING	"pcm051 U-Boot SPL"
 #define CONFIG_SPL_ETH_SUPPORT
 #define CONFIG_SPL_SPI_SUPPORT
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 788207d..98dd083 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -22,6 +22,19 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#ifdef FTRACE
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE	(16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR		0x00100000
+
+#endif
+
+#define CONFIG_BOOTSTAGE
+#define CONFIG_BOOTSTAGE_REPORT
+
 /* Number of bits in a C 'long' on this architecture */
 #define CONFIG_SANDBOX_BITS_PER_LONG	64
 
@@ -30,6 +43,8 @@
 #define CONFIG_OF_LIBFDT
 #define CONFIG_LMB
 #define CONFIG_FIT
+#define CONFIG_FIT_SIGNATURE
+#define CONFIG_RSA
 #define CONFIG_CMD_FDT
 
 #define CONFIG_FS_FAT
diff --git a/include/configs/smdkv310.h b/include/configs/smdkv310.h
index b796b46..5e43066 100644
--- a/include/configs/smdkv310.h
+++ b/include/configs/smdkv310.h
@@ -95,6 +95,8 @@
 #define CONFIG_SPL
 #define COPY_BL2_FNPTR_ADDR	0x00002488
 
+#define CONFIG_SPL_TEXT_BASE	0x02021410
+
 #define CONFIG_BOOTCOMMAND	"fatload mmc 0 40007000 uImage; bootm 40007000"
 
 /* Miscellaneous configurable options */
diff --git a/include/configs/t4qds.h b/include/configs/t4qds.h
index aa90249..92b2179 100644
--- a/include/configs/t4qds.h
+++ b/include/configs/t4qds.h
@@ -33,6 +33,15 @@
 #define CONFIG_PBLRCW_CONFIG $(SRCTREE)/board/freescale/t4qds/t4_rcw.cfg
 #endif
 
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+/* Set 1M boot space */
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR (CONFIG_SYS_TEXT_BASE & 0xfff00000)
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS \
+		(0x300000000ull | CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR)
+#define CONFIG_RESET_VECTOR_ADDRESS 0xfffffffc
+#define CONFIG_SYS_NO_FLASH
+#endif
+
 #define CONFIG_CMD_REGINFO
 
 /* High Level Configuration Options */
@@ -65,20 +74,22 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1			/* SRIO port 1 */
 #define CONFIG_SRIO2			/* SRIO port 2 */
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 
 #define CONFIG_FSL_LAW			/* Use common FSL init code */
 
 #define CONFIG_ENV_OVERWRITE
 
 #ifdef CONFIG_SYS_NO_FLASH
+#if !defined(CONFIG_SRIO_PCIE_BOOT_SLAVE) && !defined(CONFIG_RAMBOOT_PBL)
 #define CONFIG_ENV_IS_NOWHERE
+#endif
 #else
 #define CONFIG_FLASH_CFI_DRIVER
 #define CONFIG_SYS_FLASH_CFI
 #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
 #endif
 
-#ifndef CONFIG_SYS_NO_FLASH
 #if defined(CONFIG_SPIFLASH)
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #define CONFIG_ENV_IS_IN_SPI_FLASH
@@ -100,18 +111,18 @@
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE			CONFIG_SYS_NAND_BLOCK_SIZE
 #define CONFIG_ENV_OFFSET		(5 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+#define CONFIG_ENV_IS_IN_REMOTE
+#define CONFIG_ENV_ADDR		0xffe20000
+#define CONFIG_ENV_SIZE		0x2000
+#elif defined(CONFIG_ENV_IS_NOWHERE)
+#define CONFIG_ENV_SIZE		0x2000
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SECT_SIZE)
 #define CONFIG_ENV_SIZE		0x2000
 #define CONFIG_ENV_SECT_SIZE	0x20000 /* 128K (one sector) */
 #endif
-#else /* CONFIG_SYS_NO_FLASH */
-#define CONFIG_ENV_SIZE                0x2000
-#define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
-#endif
-
-
 
 #define CONFIG_SYS_CLK_FREQ	get_board_sys_clk()
 #define CONFIG_DDR_CLK_FREQ	get_board_ddr_clk()
@@ -633,6 +644,16 @@
 #elif defined(CONFIG_NAND)
 #define CONFIG_SYS_QE_FMAN_FW_IN_NAND
 #define CONFIG_SYS_QE_FMAN_FW_ADDR	(6 * 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
+ * in two corenet boards, slave's ucode could be stored in master's memory
+ * space, the address can be mapped from slave TLB->slave LAW->
+ * slave SRIO or PCIE outbound window->master inbound window->
+ * master LAW->the ucode address in master's memory space.
+ */
+#define CONFIG_SYS_QE_FMAN_FW_IN_REMOTE
+#define CONFIG_SYS_QE_FMAN_FW_ADDR	0xFFE00000
 #else
 #define CONFIG_SYS_QE_FMAN_FW_IN_NOR
 #define CONFIG_SYS_QE_FMAN_FW_ADDR		0xEFF40000
diff --git a/include/configs/trats.h b/include/configs/trats.h
index fd58558..c70838b 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -146,7 +146,8 @@
 
 #define CONFIG_DFU_ALT \
 	"u-boot mmc 80 400;" \
-	"uImage ext4 0 2\0" \
+	"uImage ext4 0 2;" \
+	"exynos4210-trats.dtb ext4 0 2\0"
 
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
@@ -154,7 +155,7 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"bootk=" \
-		"run loaduimage; bootm 0x40007FC0\0" \
+		"run loaddtb; run loaduimage; bootm 0x40007FC0 - ${fdtaddr}\0" \
 	"updatemmc=" \
 		"mmc boot 0 1 1 1; mmc write 0 0x42008000 0 0x200;" \
 		"mmc boot 0 1 1 0\0" \
@@ -177,7 +178,7 @@
 	"mmcboot=" \
 		"setenv bootargs root=/dev/mmcblk${mmcdev}p${mmcrootpart} " \
 		"${lpj} rootwait ${console} ${meminfo} ${opts} ${lcdinfo}; " \
-		"run loaduimage; bootm 0x40007FC0\0" \
+		"run loaddtb; run loaduimage; bootm 0x40007FC0 - ${fdtaddr}\0" \
 	"bootchart=setenv opts init=/sbin/bootchartd; run bootcmd\0" \
 	"boottrace=setenv opts initcall_debug; run bootcmd\0" \
 	"mmcoops=mmc read 0 0x40000000 0x40 8; md 0x40000000 0x400\0" \
@@ -188,6 +189,8 @@
 	"nfsroot=/nfsroot/arm\0" \
 	"bootblock=" CONFIG_BOOTBLOCK "\0" \
 	"loaduimage=ext4load mmc ${mmcdev}:${mmcbootpart} 0x40007FC0 uImage\0" \
+	"loaddtb=ext4load mmc ${mmcdev}:${mmcbootpart} ${fdtaddr}" \
+		"${fdtfile}\0" \
 	"mmcdev=0\0" \
 	"mmcbootpart=2\0" \
 	"mmcrootpart=5\0" \
@@ -212,7 +215,10 @@
 		   " /${splfile} ${spl_imgaddr} ${spl_imgsize};" \
 		   "setenv spl_imgsize;" \
 		   "setenv spl_imgaddr;" \
-		   "setenv spl_addr_tmp;\0"
+		   "setenv spl_addr_tmp;\0" \
+	"fdtaddr=40800000\0" \
+	"fdtfile=exynos4210-trats.dtb\0"
+
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
@@ -322,4 +328,7 @@
 #define CONFIG_USB_GADGET_MASS_STORAGE
 #endif
 
+/* Pass open firmware flat tree */
+#define CONFIG_OF_LIBFDT    1
+
 #endif	/* __CONFIG_H */
diff --git a/include/cros_ec.h b/include/cros_ec.h
new file mode 100644
index 0000000..335d5b4
--- /dev/null
+++ b/include/cros_ec.h
@@ -0,0 +1,449 @@
+/*
+ * Chromium OS cros_ec driver
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+#ifndef _CROS_EC_H
+#define _CROS_EC_H
+
+#include <linux/compiler.h>
+#include <ec_commands.h>
+#include <fdtdec.h>
+#include <cros_ec_message.h>
+
+/* Which interface is the device on? */
+enum cros_ec_interface_t {
+	CROS_EC_IF_NONE,
+	CROS_EC_IF_SPI,
+	CROS_EC_IF_I2C,
+	CROS_EC_IF_LPC,	/* Intel Low Pin Count interface */
+};
+
+/* Our configuration information */
+struct cros_ec_dev {
+	enum cros_ec_interface_t interface;
+	struct spi_slave *spi;		/* Our SPI slave, if using SPI */
+	int node;                       /* Our node */
+	int parent_node;		/* Our parent node (interface) */
+	unsigned int cs;		/* Our chip select */
+	unsigned int addr;		/* Device address (for I2C) */
+	unsigned int bus_num;		/* Bus number (for I2C) */
+	unsigned int max_frequency;	/* Maximum interface frequency */
+	struct fdt_gpio_state ec_int;	/* GPIO used as EC interrupt line */
+	int cmd_version_is_supported;   /* Device supports command versions */
+	int optimise_flash_write;	/* Don't write erased flash blocks */
+
+	/*
+	 * These two buffers will always be dword-aligned and include enough
+	 * space for up to 7 word-alignment bytes also, so we can ensure that
+	 * the body of the message is always dword-aligned (64-bit).
+	 *
+	 * We use this alignment to keep ARM and x86 happy. Probably word
+	 * alignment would be OK, there might be a small performance advantage
+	 * to using dword.
+	 */
+	uint8_t din[ALIGN(MSG_BYTES + sizeof(int64_t), sizeof(int64_t))]
+		__aligned(sizeof(int64_t));
+	uint8_t dout[ALIGN(MSG_BYTES + sizeof(int64_t), sizeof(int64_t))]
+		__aligned(sizeof(int64_t));
+};
+
+/*
+ * Hard-code the number of columns we happen to know we have right now.  It
+ * would be more correct to call cros_ec_info() at startup and determine the
+ * actual number of keyboard cols from there.
+ */
+#define CROS_EC_KEYSCAN_COLS 13
+
+/* Information returned by a key scan */
+struct mbkp_keyscan {
+	uint8_t data[CROS_EC_KEYSCAN_COLS];
+};
+
+/**
+ * Read the ID of the CROS-EC device
+ *
+ * The ID is a string identifying the CROS-EC device.
+ *
+ * @param dev		CROS-EC device
+ * @param id		Place to put the ID
+ * @param maxlen	Maximum length of the ID field
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen);
+
+/**
+ * Read a keyboard scan from the CROS-EC device
+ *
+ * Send a message requesting a keyboard scan and return the result
+ *
+ * @param dev		CROS-EC device
+ * @param scan		Place to put the scan results
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_scan_keyboard(struct cros_ec_dev *dev, struct mbkp_keyscan *scan);
+
+/**
+ * Read which image is currently running on the CROS-EC device.
+ *
+ * @param dev		CROS-EC device
+ * @param image		Destination for image identifier
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_read_current_image(struct cros_ec_dev *dev,
+		enum ec_current_image *image);
+
+/**
+ * Read the hash of the CROS-EC device firmware.
+ *
+ * @param dev		CROS-EC device
+ * @param hash		Destination for hash information
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_read_hash(struct cros_ec_dev *dev,
+		struct ec_response_vboot_hash *hash);
+
+/**
+ * Send a reboot command to the CROS-EC device.
+ *
+ * Note that some reboot commands (such as EC_REBOOT_COLD) also reboot the AP.
+ *
+ * @param dev		CROS-EC device
+ * @param cmd		Reboot command
+ * @param flags         Flags for reboot command (EC_REBOOT_FLAG_*)
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd,
+		uint8_t flags);
+
+/**
+ * Check if the CROS-EC device has an interrupt pending.
+ *
+ * Read the status of the external interrupt connected to the CROS-EC device.
+ * If no external interrupt is configured, this always returns 1.
+ *
+ * @param dev		CROS-EC device
+ * @return 0 if no interrupt is pending
+ */
+int cros_ec_interrupt_pending(struct cros_ec_dev *dev);
+
+enum {
+	CROS_EC_OK,
+	CROS_EC_ERR = 1,
+	CROS_EC_ERR_FDT_DECODE,
+	CROS_EC_ERR_CHECK_VERSION,
+	CROS_EC_ERR_READ_ID,
+	CROS_EC_ERR_DEV_INIT,
+};
+
+/**
+ * Set up the Chromium OS matrix keyboard protocol
+ *
+ * @param blob		Device tree blob containing setup information
+ * @param cros_ecp        Returns pointer to the cros_ec device, or NULL if none
+ * @return 0 if we got an cros_ec device and all is well (or no cros_ec is
+ *	expected), -ve if we should have an cros_ec device but failed to find
+ *	one, or init failed (-CROS_EC_ERR_...).
+ */
+int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp);
+
+/**
+ * Read information about the keyboard matrix
+ *
+ * @param dev		CROS-EC device
+ * @param info		Place to put the info structure
+ */
+int cros_ec_info(struct cros_ec_dev *dev,
+		struct ec_response_cros_ec_info *info);
+
+/**
+ * Read the host event flags
+ *
+ * @param dev		CROS-EC device
+ * @param events_ptr	Destination for event flags.  Not changed on error.
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr);
+
+/**
+ * Clear the specified host event flags
+ *
+ * @param dev		CROS-EC device
+ * @param events	Event flags to clear
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events);
+
+/**
+ * Get/set flash protection
+ *
+ * @param dev		CROS-EC device
+ * @param set_mask	Mask of flags to set; if 0, just retrieves existing
+ *                      protection state without changing it.
+ * @param set_flags	New flag values; only bits in set_mask are applied;
+ *                      ignored if set_mask=0.
+ * @param prot          Destination for updated protection state from EC.
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_flash_protect(struct cros_ec_dev *dev,
+		       uint32_t set_mask, uint32_t set_flags,
+		       struct ec_response_flash_protect *resp);
+
+
+/**
+ * Run internal tests on the cros_ec interface.
+ *
+ * @param dev		CROS-EC device
+ * @return 0 if ok, <0 if the test failed
+ */
+int cros_ec_test(struct cros_ec_dev *dev);
+
+/**
+ * Update the EC RW copy.
+ *
+ * @param dev		CROS-EC device
+ * @param image		the content to write
+ * @param imafge_size	content length
+ * @return 0 if ok, <0 if the test failed
+ */
+int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
+			 const uint8_t  *image, int image_size);
+
+/**
+ * Return a pointer to the board's CROS-EC device
+ *
+ * This should be implemented by board files.
+ *
+ * @return pointer to CROS-EC device, or NULL if none is available
+ */
+struct cros_ec_dev *board_get_cros_ec_dev(void);
+
+
+/* Internal interfaces */
+int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob);
+int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob);
+int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob);
+
+/**
+ * Read information from the fdt for the i2c cros_ec interface
+ *
+ * @param dev		CROS-EC device
+ * @param blob		Device tree blob
+ * @return 0 if ok, -1 if we failed to read all required information
+ */
+int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob);
+
+/**
+ * Read information from the fdt for the spi cros_ec interface
+ *
+ * @param dev		CROS-EC device
+ * @param blob		Device tree blob
+ * @return 0 if ok, -1 if we failed to read all required information
+ */
+int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob);
+
+/**
+ * Check whether the LPC interface supports new-style commands.
+ *
+ * LPC has its own way of doing this, which involves checking LPC values
+ * visible to the host. Do this, and update dev->cmd_version_is_supported
+ * accordingly.
+ *
+ * @param dev		CROS-EC device to check
+ */
+int cros_ec_lpc_check_version(struct cros_ec_dev *dev);
+
+/**
+ * Send a command to an I2C CROS-EC device and return the reply.
+ *
+ * This rather complicated function deals with sending both old-style and
+ * new-style commands. The old ones have just a command byte and arguments.
+ * The new ones have version, command, arg-len, [args], chksum so are 3 bytes
+ * longer.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev		CROS-EC device
+ * @param cmd		Command to send (EC_CMD_...)
+ * @param cmd_version	Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Returns pointer to response data
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len);
+
+/**
+ * Send a command to a LPC CROS-EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev		CROS-EC device
+ * @param cmd		Command to send (EC_CMD_...)
+ * @param cmd_version	Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Returns pointer to response data
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+int cros_ec_lpc_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len);
+
+int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+		     const uint8_t *dout, int dout_len,
+		     uint8_t **dinp, int din_len);
+
+/**
+ * Dump a block of data for a command.
+ *
+ * @param name	Name for data (e.g. 'in', 'out')
+ * @param cmd	Command number associated with data, or -1 for none
+ * @param data	Data block to dump
+ * @param len	Length of data block to dump
+ */
+void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len);
+
+/**
+ * Calculate a simple 8-bit checksum of a data block
+ *
+ * @param data	Data block to checksum
+ * @param size	Size of data block in bytes
+ * @return checksum value (0 to 255)
+ */
+int cros_ec_calc_checksum(const uint8_t *data, int size);
+
+/**
+ * Decode a flash region parameter
+ *
+ * @param argc	Number of params remaining
+ * @param argv	List of remaining parameters
+ * @return flash region (EC_FLASH_REGION_...) or -1 on error
+ */
+int cros_ec_decode_region(int argc, char * const argv[]);
+
+int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset,
+		uint32_t size);
+
+/**
+ * Read data from the flash
+ *
+ * Read an arbitrary amount of data from the EC flash, by repeatedly reading
+ * small blocks.
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to read for a particular region.
+ *
+ * @param dev		CROS-EC device
+ * @param data		Pointer to data buffer to read into
+ * @param offset	Offset within flash to read from
+ * @param size		Number of bytes to read
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
+		    uint32_t size);
+
+/**
+ * Write data to the flash
+ *
+ * Write an arbitrary amount of data to the EC flash, by repeatedly writing
+ * small blocks.
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to write for a particular region.
+ *
+ * Attempting to write to the region where the EC is currently running from
+ * will result in an error.
+ *
+ * @param dev		CROS-EC device
+ * @param data		Pointer to data buffer to write
+ * @param offset	Offset within flash to write to.
+ * @param size		Number of bytes to write
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
+		     uint32_t offset, uint32_t size);
+
+/**
+ * Obtain position and size of a flash region
+ *
+ * @param dev		CROS-EC device
+ * @param region	Flash region to query
+ * @param offset	Returns offset of flash region in EC flash
+ * @param size		Returns size of flash region
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region,
+		      uint32_t *offset, uint32_t *size);
+
+/**
+ * Read/write VbNvContext from/to a CROS-EC device.
+ *
+ * @param dev		CROS-EC device
+ * @param block		Buffer of VbNvContext to be read/write
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block);
+int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block);
+
+/**
+ * Read the version information for the EC images
+ *
+ * @param dev		CROS-EC device
+ * @param versionp	This is set to point to the version information
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_version(struct cros_ec_dev *dev,
+		       struct ec_response_get_version **versionp);
+
+/**
+ * Read the build information for the EC
+ *
+ * @param dev		CROS-EC device
+ * @param versionp	This is set to point to the build string
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp);
+
+/**
+ * Switch on/off a LDO / FET.
+ *
+ * @param dev		CROS-EC device
+ * @param index		index of the LDO/FET to switch
+ * @param state		new state of the LDO/FET : EC_LDO_STATE_ON|OFF
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state);
+
+/**
+ * Read back a LDO / FET current state.
+ *
+ * @param dev		CROS-EC device
+ * @param index		index of the LDO/FET to switch
+ * @param state		current state of the LDO/FET : EC_LDO_STATE_ON|OFF
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state);
+#endif
diff --git a/include/cros_ec_message.h b/include/cros_ec_message.h
new file mode 100644
index 0000000..a2421c7
--- /dev/null
+++ b/include/cros_ec_message.h
@@ -0,0 +1,44 @@
+/*
+ * Chromium OS Matrix Keyboard Message Protocol definitions
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * 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
+ */
+
+#ifndef _CROS_MESSAGE_H
+#define _CROS_MESSAGE_H
+
+/*
+ * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
+ *
+ * This is copied from the Chromium OS Open Source Embedded Controller code.
+ */
+enum {
+	/* The header byte, which follows the preamble */
+	MSG_HEADER	= 0xec,
+
+	MSG_HEADER_BYTES	= 3,
+	MSG_TRAILER_BYTES	= 2,
+	MSG_PROTO_BYTES		= MSG_HEADER_BYTES + MSG_TRAILER_BYTES,
+
+	/* Max length of messages */
+	MSG_BYTES		= EC_HOST_PARAM_SIZE + MSG_PROTO_BYTES,
+};
+
+#endif
diff --git a/include/dwmmc.h b/include/dwmmc.h
index c8b1d40..e142f3e 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -123,6 +123,8 @@
 #define MSIZE(x)		((x) << 28)
 #define RX_WMARK(x)		((x) << 16)
 #define TX_WMARK(x)		(x)
+#define RX_WMARK_SHIFT		16
+#define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)
 
 #define DWMCI_IDMAC_OWN		(1 << 31)
 #define DWMCI_IDMAC_CH		(1 << 4)
@@ -144,6 +146,7 @@
 	unsigned int bus_hz;
 	int dev_index;
 	int buswidth;
+	u32 clksel_val;
 	u32 fifoth_val;
 	struct mmc *mmc;
 
diff --git a/include/ec_commands.h b/include/ec_commands.h
new file mode 100644
index 0000000..12811cc
--- /dev/null
+++ b/include/ec_commands.h
@@ -0,0 +1,1440 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Host communication command constants for Chrome EC */
+
+#ifndef __CROS_EC_COMMANDS_H
+#define __CROS_EC_COMMANDS_H
+
+/*
+ * Protocol overview
+ *
+ * request:  CMD [ P0 P1 P2 ... Pn S ]
+ * response: ERR [ P0 P1 P2 ... Pn S ]
+ *
+ * where the bytes are defined as follow :
+ *      - CMD is the command code. (defined by EC_CMD_ constants)
+ *      - ERR is the error code. (defined by EC_RES_ constants)
+ *      - Px is the optional payload.
+ *        it is not sent if the error code is not success.
+ *        (defined by ec_params_ and ec_response_ structures)
+ *      - S is the checksum which is the sum of all payload bytes.
+ *
+ * On LPC, CMD and ERR are sent/received at EC_LPC_ADDR_KERNEL|USER_CMD
+ * and the payloads are sent/received at EC_LPC_ADDR_KERNEL|USER_PARAM.
+ * On I2C, all bytes are sent serially in the same message.
+ */
+
+/* Current version of this protocol */
+#define EC_PROTO_VERSION          0x00000002
+
+/* Command version mask */
+#define EC_VER_MASK(version) (1UL << (version))
+
+/* I/O addresses for ACPI commands */
+#define EC_LPC_ADDR_ACPI_DATA  0x62
+#define EC_LPC_ADDR_ACPI_CMD   0x66
+
+/* I/O addresses for host command */
+#define EC_LPC_ADDR_HOST_DATA  0x200
+#define EC_LPC_ADDR_HOST_CMD   0x204
+
+/* I/O addresses for host command args and params */
+#define EC_LPC_ADDR_HOST_ARGS  0x800
+#define EC_LPC_ADDR_HOST_PARAM 0x804
+#define EC_HOST_PARAM_SIZE     0x0fc  /* Size of param area in bytes */
+
+/* I/O addresses for host command params, old interface */
+#define EC_LPC_ADDR_OLD_PARAM  0x880
+#define EC_OLD_PARAM_SIZE      0x080  /* Size of param area in bytes */
+
+/* EC command register bit functions */
+#define EC_LPC_CMDR_DATA	(1 << 0)  /* Data ready for host to read */
+#define EC_LPC_CMDR_PENDING	(1 << 1)  /* Write pending to EC */
+#define EC_LPC_CMDR_BUSY	(1 << 2)  /* EC is busy processing a command */
+#define EC_LPC_CMDR_CMD		(1 << 3)  /* Last host write was a command */
+#define EC_LPC_CMDR_ACPI_BRST	(1 << 4)  /* Burst mode (not used) */
+#define EC_LPC_CMDR_SCI		(1 << 5)  /* SCI event is pending */
+#define EC_LPC_CMDR_SMI		(1 << 6)  /* SMI event is pending */
+
+#define EC_LPC_ADDR_MEMMAP       0x900
+#define EC_MEMMAP_SIZE         255 /* ACPI IO buffer max is 255 bytes */
+#define EC_MEMMAP_TEXT_MAX     8   /* Size of a string in the memory map */
+
+/* The offset address of each type of data in mapped memory. */
+#define EC_MEMMAP_TEMP_SENSOR      0x00 /* Temp sensors */
+#define EC_MEMMAP_FAN              0x10 /* Fan speeds */
+#define EC_MEMMAP_TEMP_SENSOR_B    0x18 /* Temp sensors (second set) */
+#define EC_MEMMAP_ID               0x20 /* 'E' 'C' */
+#define EC_MEMMAP_ID_VERSION       0x22 /* Version of data in 0x20 - 0x2f */
+#define EC_MEMMAP_THERMAL_VERSION  0x23 /* Version of data in 0x00 - 0x1f */
+#define EC_MEMMAP_BATTERY_VERSION  0x24 /* Version of data in 0x40 - 0x7f */
+#define EC_MEMMAP_SWITCHES_VERSION 0x25 /* Version of data in 0x30 - 0x33 */
+#define EC_MEMMAP_EVENTS_VERSION   0x26 /* Version of data in 0x34 - 0x3f */
+#define EC_MEMMAP_HOST_CMD_FLAGS   0x27 /* Host command interface flags */
+#define EC_MEMMAP_SWITCHES         0x30
+#define EC_MEMMAP_HOST_EVENTS      0x34
+#define EC_MEMMAP_BATT_VOLT        0x40 /* Battery Present Voltage */
+#define EC_MEMMAP_BATT_RATE        0x44 /* Battery Present Rate */
+#define EC_MEMMAP_BATT_CAP         0x48 /* Battery Remaining Capacity */
+#define EC_MEMMAP_BATT_FLAG        0x4c /* Battery State, defined below */
+#define EC_MEMMAP_BATT_DCAP        0x50 /* Battery Design Capacity */
+#define EC_MEMMAP_BATT_DVLT        0x54 /* Battery Design Voltage */
+#define EC_MEMMAP_BATT_LFCC        0x58 /* Battery Last Full Charge Capacity */
+#define EC_MEMMAP_BATT_CCNT        0x5c /* Battery Cycle Count */
+#define EC_MEMMAP_BATT_MFGR        0x60 /* Battery Manufacturer String */
+#define EC_MEMMAP_BATT_MODEL       0x68 /* Battery Model Number String */
+#define EC_MEMMAP_BATT_SERIAL      0x70 /* Battery Serial Number String */
+#define EC_MEMMAP_BATT_TYPE        0x78 /* Battery Type String */
+
+/* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */
+#define EC_TEMP_SENSOR_ENTRIES     16
+/*
+ * Number of temp sensors at EC_MEMMAP_TEMP_SENSOR_B.
+ *
+ * Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2.
+ */
+#define EC_TEMP_SENSOR_B_ENTRIES      8
+#define EC_TEMP_SENSOR_NOT_PRESENT    0xff
+#define EC_TEMP_SENSOR_ERROR          0xfe
+#define EC_TEMP_SENSOR_NOT_POWERED    0xfd
+#define EC_TEMP_SENSOR_NOT_CALIBRATED 0xfc
+/*
+ * The offset of temperature value stored in mapped memory.  This allows
+ * reporting a temperature range of 200K to 454K = -73C to 181C.
+ */
+#define EC_TEMP_SENSOR_OFFSET      200
+
+#define EC_FAN_SPEED_ENTRIES       4       /* Number of fans at EC_MEMMAP_FAN */
+#define EC_FAN_SPEED_NOT_PRESENT   0xffff  /* Entry not present */
+#define EC_FAN_SPEED_STALLED       0xfffe  /* Fan stalled */
+
+/* Battery bit flags at EC_MEMMAP_BATT_FLAG. */
+#define EC_BATT_FLAG_AC_PRESENT   0x01
+#define EC_BATT_FLAG_BATT_PRESENT 0x02
+#define EC_BATT_FLAG_DISCHARGING  0x04
+#define EC_BATT_FLAG_CHARGING     0x08
+#define EC_BATT_FLAG_LEVEL_CRITICAL 0x10
+
+/* Switch flags at EC_MEMMAP_SWITCHES */
+#define EC_SWITCH_LID_OPEN               0x01
+#define EC_SWITCH_POWER_BUTTON_PRESSED   0x02
+#define EC_SWITCH_WRITE_PROTECT_DISABLED 0x04
+/* Recovery requested via keyboard */
+#define EC_SWITCH_KEYBOARD_RECOVERY      0x08
+/* Recovery requested via dedicated signal (from servo board) */
+#define EC_SWITCH_DEDICATED_RECOVERY     0x10
+/* Was fake developer mode switch; now unused.  Remove in next refactor. */
+#define EC_SWITCH_IGNORE0                0x20
+
+/* Host command interface flags */
+/* Host command interface supports LPC args (LPC interface only) */
+#define EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED  0x01
+
+/* Wireless switch flags */
+#define EC_WIRELESS_SWITCH_WLAN      0x01
+#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02
+
+/*
+ * This header file is used in coreboot both in C and ACPI code.  The ACPI code
+ * is pre-processed to handle constants but the ASL compiler is unable to
+ * handle actual C code so keep it separate.
+ */
+#ifndef __ACPI__
+
+/*
+ * Define __packed if someone hasn't beat us to it.  Linux kernel style
+ * checking prefers __packed over __attribute__((packed)).
+ */
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+/* LPC command status byte masks */
+/* EC has written a byte in the data register and host hasn't read it yet */
+#define EC_LPC_STATUS_TO_HOST     0x01
+/* Host has written a command/data byte and the EC hasn't read it yet */
+#define EC_LPC_STATUS_FROM_HOST   0x02
+/* EC is processing a command */
+#define EC_LPC_STATUS_PROCESSING  0x04
+/* Last write to EC was a command, not data */
+#define EC_LPC_STATUS_LAST_CMD    0x08
+/* EC is in burst mode.  Unsupported by Chrome EC, so this bit is never set */
+#define EC_LPC_STATUS_BURST_MODE  0x10
+/* SCI event is pending (requesting SCI query) */
+#define EC_LPC_STATUS_SCI_PENDING 0x20
+/* SMI event is pending (requesting SMI query) */
+#define EC_LPC_STATUS_SMI_PENDING 0x40
+/* (reserved) */
+#define EC_LPC_STATUS_RESERVED    0x80
+
+/*
+ * EC is busy.  This covers both the EC processing a command, and the host has
+ * written a new command but the EC hasn't picked it up yet.
+ */
+#define EC_LPC_STATUS_BUSY_MASK \
+	(EC_LPC_STATUS_FROM_HOST | EC_LPC_STATUS_PROCESSING)
+
+/* Host command response codes */
+enum ec_status {
+	EC_RES_SUCCESS = 0,
+	EC_RES_INVALID_COMMAND = 1,
+	EC_RES_ERROR = 2,
+	EC_RES_INVALID_PARAM = 3,
+	EC_RES_ACCESS_DENIED = 4,
+	EC_RES_INVALID_RESPONSE = 5,
+	EC_RES_INVALID_VERSION = 6,
+	EC_RES_INVALID_CHECKSUM = 7,
+	EC_RES_IN_PROGRESS = 8,		/* Accepted, command in progress */
+	EC_RES_UNAVAILABLE = 9,		/* No response available */
+	EC_RES_TIMEOUT = 10,		/* We got a timeout */
+	EC_RES_OVERFLOW = 11,		/* Table / data overflow */
+};
+
+/*
+ * Host event codes.  Note these are 1-based, not 0-based, because ACPI query
+ * EC command uses code 0 to mean "no event pending".  We explicitly specify
+ * each value in the enum listing so they won't change if we delete/insert an
+ * item or rearrange the list (it needs to be stable across platforms, not
+ * just within a single compiled instance).
+ */
+enum host_event_code {
+	EC_HOST_EVENT_LID_CLOSED = 1,
+	EC_HOST_EVENT_LID_OPEN = 2,
+	EC_HOST_EVENT_POWER_BUTTON = 3,
+	EC_HOST_EVENT_AC_CONNECTED = 4,
+	EC_HOST_EVENT_AC_DISCONNECTED = 5,
+	EC_HOST_EVENT_BATTERY_LOW = 6,
+	EC_HOST_EVENT_BATTERY_CRITICAL = 7,
+	EC_HOST_EVENT_BATTERY = 8,
+	EC_HOST_EVENT_THERMAL_THRESHOLD = 9,
+	EC_HOST_EVENT_THERMAL_OVERLOAD = 10,
+	EC_HOST_EVENT_THERMAL = 11,
+	EC_HOST_EVENT_USB_CHARGER = 12,
+	EC_HOST_EVENT_KEY_PRESSED = 13,
+	/*
+	 * EC has finished initializing the host interface.  The host can check
+	 * for this event following sending a EC_CMD_REBOOT_EC command to
+	 * determine when the EC is ready to accept subsequent commands.
+	 */
+	EC_HOST_EVENT_INTERFACE_READY = 14,
+	/* Keyboard recovery combo has been pressed */
+	EC_HOST_EVENT_KEYBOARD_RECOVERY = 15,
+
+	/* Shutdown due to thermal overload */
+	EC_HOST_EVENT_THERMAL_SHUTDOWN = 16,
+	/* Shutdown due to battery level too low */
+	EC_HOST_EVENT_BATTERY_SHUTDOWN = 17,
+
+	/*
+	 * The high bit of the event mask is not used as a host event code.  If
+	 * it reads back as set, then the entire event mask should be
+	 * considered invalid by the host.  This can happen when reading the
+	 * raw event status via EC_MEMMAP_HOST_EVENTS but the LPC interface is
+	 * not initialized on the EC, or improperly configured on the host.
+	 */
+	EC_HOST_EVENT_INVALID = 32
+};
+/* Host event mask */
+#define EC_HOST_EVENT_MASK(event_code) (1UL << ((event_code) - 1))
+
+/* Arguments at EC_LPC_ADDR_HOST_ARGS */
+struct ec_lpc_host_args {
+	uint8_t flags;
+	uint8_t command_version;
+	uint8_t data_size;
+	/*
+	 * Checksum; sum of command + flags + command_version + data_size +
+	 * all params/response data bytes.
+	 */
+	uint8_t checksum;
+} __packed;
+
+/* Flags for ec_lpc_host_args.flags */
+/*
+ * Args are from host.  Data area at EC_LPC_ADDR_HOST_PARAM contains command
+ * params.
+ *
+ * If EC gets a command and this flag is not set, this is an old-style command.
+ * Command version is 0 and params from host are at EC_LPC_ADDR_OLD_PARAM with
+ * unknown length.  EC must respond with an old-style response (that is,
+ * withouth setting EC_HOST_ARGS_FLAG_TO_HOST).
+ */
+#define EC_HOST_ARGS_FLAG_FROM_HOST 0x01
+/*
+ * Args are from EC.  Data area at EC_LPC_ADDR_HOST_PARAM contains response.
+ *
+ * If EC responds to a command and this flag is not set, this is an old-style
+ * response.  Command version is 0 and response data from EC is at
+ * EC_LPC_ADDR_OLD_PARAM with unknown length.
+ */
+#define EC_HOST_ARGS_FLAG_TO_HOST   0x02
+
+/*
+ * Notes on commands:
+ *
+ * Each command is an 8-byte command value.  Commands which take params or
+ * return response data specify structs for that data.  If no struct is
+ * specified, the command does not input or output data, respectively.
+ * Parameter/response length is implicit in the structs.  Some underlying
+ * communication protocols (I2C, SPI) may add length or checksum headers, but
+ * those are implementation-dependent and not defined here.
+ */
+
+/*****************************************************************************/
+/* General / test commands */
+
+/*
+ * Get protocol version, used to deal with non-backward compatible protocol
+ * changes.
+ */
+#define EC_CMD_PROTO_VERSION 0x00
+
+struct ec_response_proto_version {
+	uint32_t version;
+} __packed;
+
+/*
+ * Hello.  This is a simple command to test the EC is responsive to
+ * commands.
+ */
+#define EC_CMD_HELLO 0x01
+
+struct ec_params_hello {
+	uint32_t in_data;  /* Pass anything here */
+} __packed;
+
+struct ec_response_hello {
+	uint32_t out_data;  /* Output will be in_data + 0x01020304 */
+} __packed;
+
+/* Get version number */
+#define EC_CMD_GET_VERSION 0x02
+
+enum ec_current_image {
+	EC_IMAGE_UNKNOWN = 0,
+	EC_IMAGE_RO,
+	EC_IMAGE_RW
+};
+
+struct ec_response_get_version {
+	/* Null-terminated version strings for RO, RW */
+	char version_string_ro[32];
+	char version_string_rw[32];
+	char reserved[32];       /* Was previously RW-B string */
+	uint32_t current_image;  /* One of ec_current_image */
+} __packed;
+
+/* Read test */
+#define EC_CMD_READ_TEST 0x03
+
+struct ec_params_read_test {
+	uint32_t offset;   /* Starting value for read buffer */
+	uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+struct ec_response_read_test {
+	uint32_t data[32];
+} __packed;
+
+/*
+ * Get build information
+ *
+ * Response is null-terminated string.
+ */
+#define EC_CMD_GET_BUILD_INFO 0x04
+
+/* Get chip info */
+#define EC_CMD_GET_CHIP_INFO 0x05
+
+struct ec_response_get_chip_info {
+	/* Null-terminated strings */
+	char vendor[32];
+	char name[32];
+	char revision[32];  /* Mask version */
+} __packed;
+
+/* Get board HW version */
+#define EC_CMD_GET_BOARD_VERSION 0x06
+
+struct ec_response_board_version {
+	uint16_t board_version;  /* A monotonously incrementing number. */
+} __packed;
+
+/*
+ * Read memory-mapped data.
+ *
+ * This is an alternate interface to memory-mapped data for bus protocols
+ * which don't support direct-mapped memory - I2C, SPI, etc.
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_READ_MEMMAP 0x07
+
+struct ec_params_read_memmap {
+	uint8_t offset;   /* Offset in memmap (EC_MEMMAP_*) */
+	uint8_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Read versions supported for a command */
+#define EC_CMD_GET_CMD_VERSIONS 0x08
+
+struct ec_params_get_cmd_versions {
+	uint8_t cmd;      /* Command to check */
+} __packed;
+
+struct ec_response_get_cmd_versions {
+	/*
+	 * Mask of supported versions; use EC_VER_MASK() to compare with a
+	 * desired version.
+	 */
+	uint32_t version_mask;
+} __packed;
+
+/*
+ * Check EC communcations status (busy). This is needed on i2c/spi but not
+ * on lpc since it has its own out-of-band busy indicator.
+ *
+ * lpc must read the status from the command register. Attempting this on
+ * lpc will overwrite the args/parameter space and corrupt its data.
+ */
+#define EC_CMD_GET_COMMS_STATUS		0x09
+
+/* Avoid using ec_status which is for return values */
+enum ec_comms_status {
+	EC_COMMS_STATUS_PROCESSING	= 1 << 0,	/* Processing cmd */
+};
+
+struct ec_response_get_comms_status {
+	uint32_t flags;		/* Mask of enum ec_comms_status */
+} __packed;
+
+
+/*****************************************************************************/
+/* Flash commands */
+
+/* Get flash info */
+#define EC_CMD_FLASH_INFO 0x10
+
+struct ec_response_flash_info {
+	/* Usable flash size, in bytes */
+	uint32_t flash_size;
+	/*
+	 * Write block size.  Write offset and size must be a multiple
+	 * of this.
+	 */
+	uint32_t write_block_size;
+	/*
+	 * Erase block size.  Erase offset and size must be a multiple
+	 * of this.
+	 */
+	uint32_t erase_block_size;
+	/*
+	 * Protection block size.  Protection offset and size must be a
+	 * multiple of this.
+	 */
+	uint32_t protect_block_size;
+} __packed;
+
+/*
+ * Read flash
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_FLASH_READ 0x11
+
+struct ec_params_flash_read {
+	uint32_t offset;   /* Byte offset to read */
+	uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Write flash */
+#define EC_CMD_FLASH_WRITE 0x12
+
+struct ec_params_flash_write {
+	uint32_t offset;   /* Byte offset to write */
+	uint32_t size;     /* Size to write in bytes */
+	/*
+	 * Data to write.  Could really use EC_PARAM_SIZE - 8, but tidiest to
+	 * use a power of 2 so writes stay aligned.
+	 */
+	uint8_t data[64];
+} __packed;
+
+/* Erase flash */
+#define EC_CMD_FLASH_ERASE 0x13
+
+struct ec_params_flash_erase {
+	uint32_t offset;   /* Byte offset to erase */
+	uint32_t size;     /* Size to erase in bytes */
+} __packed;
+
+/*
+ * Get/set flash protection.
+ *
+ * If mask!=0, sets/clear the requested bits of flags.  Depending on the
+ * firmware write protect GPIO, not all flags will take effect immediately;
+ * some flags require a subsequent hard reset to take effect.  Check the
+ * returned flags bits to see what actually happened.
+ *
+ * If mask=0, simply returns the current flags state.
+ */
+#define EC_CMD_FLASH_PROTECT 0x15
+#define EC_VER_FLASH_PROTECT 1  /* Command version 1 */
+
+/* Flags for flash protection */
+/* RO flash code protected when the EC boots */
+#define EC_FLASH_PROTECT_RO_AT_BOOT         (1 << 0)
+/*
+ * RO flash code protected now.  If this bit is set, at-boot status cannot
+ * be changed.
+ */
+#define EC_FLASH_PROTECT_RO_NOW             (1 << 1)
+/* Entire flash code protected now, until reboot. */
+#define EC_FLASH_PROTECT_ALL_NOW            (1 << 2)
+/* Flash write protect GPIO is asserted now */
+#define EC_FLASH_PROTECT_GPIO_ASSERTED      (1 << 3)
+/* Error - at least one bank of flash is stuck locked, and cannot be unlocked */
+#define EC_FLASH_PROTECT_ERROR_STUCK        (1 << 4)
+/*
+ * Error - flash protection is in inconsistent state.  At least one bank of
+ * flash which should be protected is not protected.  Usually fixed by
+ * re-requesting the desired flags, or by a hard reset if that fails.
+ */
+#define EC_FLASH_PROTECT_ERROR_INCONSISTENT (1 << 5)
+/* Entile flash code protected when the EC boots */
+#define EC_FLASH_PROTECT_ALL_AT_BOOT        (1 << 6)
+
+struct ec_params_flash_protect {
+	uint32_t mask;   /* Bits in flags to apply */
+	uint32_t flags;  /* New flags to apply */
+} __packed;
+
+struct ec_response_flash_protect {
+	/* Current value of flash protect flags */
+	uint32_t flags;
+	/*
+	 * Flags which are valid on this platform.  This allows the caller
+	 * to distinguish between flags which aren't set vs. flags which can't
+	 * be set on this platform.
+	 */
+	uint32_t valid_flags;
+	/* Flags which can be changed given the current protection state */
+	uint32_t writable_flags;
+} __packed;
+
+/*
+ * Note: commands 0x14 - 0x19 version 0 were old commands to get/set flash
+ * write protect.  These commands may be reused with version > 0.
+ */
+
+/* Get the region offset/size */
+#define EC_CMD_FLASH_REGION_INFO 0x16
+#define EC_VER_FLASH_REGION_INFO 1
+
+enum ec_flash_region {
+	/* Region which holds read-only EC image */
+	EC_FLASH_REGION_RO,
+	/* Region which holds rewritable EC image */
+	EC_FLASH_REGION_RW,
+	/*
+	 * Region which should be write-protected in the factory (a superset of
+	 * EC_FLASH_REGION_RO)
+	 */
+	EC_FLASH_REGION_WP_RO,
+};
+
+struct ec_params_flash_region_info {
+	uint32_t region;  /* enum ec_flash_region */
+} __packed;
+
+struct ec_response_flash_region_info {
+	uint32_t offset;
+	uint32_t size;
+} __packed;
+
+/* Read/write VbNvContext */
+#define EC_CMD_VBNV_CONTEXT 0x17
+#define EC_VER_VBNV_CONTEXT 1
+#define EC_VBNV_BLOCK_SIZE 16
+
+enum ec_vbnvcontext_op {
+	EC_VBNV_CONTEXT_OP_READ,
+	EC_VBNV_CONTEXT_OP_WRITE,
+};
+
+struct ec_params_vbnvcontext {
+	uint32_t op;
+	uint8_t block[EC_VBNV_BLOCK_SIZE];
+} __packed;
+
+struct ec_response_vbnvcontext {
+	uint8_t block[EC_VBNV_BLOCK_SIZE];
+} __packed;
+
+/*****************************************************************************/
+/* PWM commands */
+
+/* Get fan target RPM */
+#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x20
+
+struct ec_response_pwm_get_fan_rpm {
+	uint32_t rpm;
+} __packed;
+
+/* Set target fan RPM */
+#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x21
+
+struct ec_params_pwm_set_fan_target_rpm {
+	uint32_t rpm;
+} __packed;
+
+/* Get keyboard backlight */
+#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x22
+
+struct ec_response_pwm_get_keyboard_backlight {
+	uint8_t percent;
+	uint8_t enabled;
+} __packed;
+
+/* Set keyboard backlight */
+#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x23
+
+struct ec_params_pwm_set_keyboard_backlight {
+	uint8_t percent;
+} __packed;
+
+/* Set target fan PWM duty cycle */
+#define EC_CMD_PWM_SET_FAN_DUTY 0x24
+
+struct ec_params_pwm_set_fan_duty {
+	uint32_t percent;
+} __packed;
+
+/*****************************************************************************/
+/*
+ * Lightbar commands. This looks worse than it is. Since we only use one HOST
+ * command to say "talk to the lightbar", we put the "and tell it to do X" part
+ * into a subcommand. We'll make separate structs for subcommands with
+ * different input args, so that we know how much to expect.
+ */
+#define EC_CMD_LIGHTBAR_CMD 0x28
+
+struct rgb_s {
+	uint8_t r, g, b;
+};
+
+#define LB_BATTERY_LEVELS 4
+/* List of tweakable parameters. NOTE: It's __packed so it can be sent in a
+ * host command, but the alignment is the same regardless. Keep it that way.
+ */
+struct lightbar_params {
+	/* Timing */
+	int google_ramp_up;
+	int google_ramp_down;
+	int s3s0_ramp_up;
+	int s0_tick_delay[2];			/* AC=0/1 */
+	int s0a_tick_delay[2];			/* AC=0/1 */
+	int s0s3_ramp_down;
+	int s3_sleep_for;
+	int s3_ramp_up;
+	int s3_ramp_down;
+
+	/* Oscillation */
+	uint8_t new_s0;
+	uint8_t osc_min[2];			/* AC=0/1 */
+	uint8_t osc_max[2];			/* AC=0/1 */
+	uint8_t w_ofs[2];			/* AC=0/1 */
+
+	/* Brightness limits based on the backlight and AC. */
+	uint8_t bright_bl_off_fixed[2];		/* AC=0/1 */
+	uint8_t bright_bl_on_min[2];		/* AC=0/1 */
+	uint8_t bright_bl_on_max[2];		/* AC=0/1 */
+
+	/* Battery level thresholds */
+	uint8_t battery_threshold[LB_BATTERY_LEVELS - 1];
+
+	/* Map [AC][battery_level] to color index */
+	uint8_t s0_idx[2][LB_BATTERY_LEVELS];	/* AP is running */
+	uint8_t s3_idx[2][LB_BATTERY_LEVELS];	/* AP is sleeping */
+
+	/* Color palette */
+	struct rgb_s color[8];			/* 0-3 are Google colors */
+} __packed;
+
+struct ec_params_lightbar {
+	uint8_t cmd;		      /* Command (see enum lightbar_command) */
+	union {
+		struct {
+			/* no args */
+		} dump, off, on, init, get_seq, get_params;
+
+		struct num {
+			uint8_t num;
+		} brightness, seq, demo;
+
+		struct reg {
+			uint8_t ctrl, reg, value;
+		} reg;
+
+		struct rgb {
+			uint8_t led, red, green, blue;
+		} rgb;
+
+		struct lightbar_params set_params;
+	};
+} __packed;
+
+struct ec_response_lightbar {
+	union {
+		struct dump {
+			struct {
+				uint8_t reg;
+				uint8_t ic0;
+				uint8_t ic1;
+			} vals[23];
+		} dump;
+
+		struct get_seq {
+			uint8_t num;
+		} get_seq;
+
+		struct lightbar_params get_params;
+
+		struct {
+			/* no return params */
+		} off, on, init, brightness, seq, reg, rgb, demo, set_params;
+	};
+} __packed;
+
+/* Lightbar commands */
+enum lightbar_command {
+	LIGHTBAR_CMD_DUMP = 0,
+	LIGHTBAR_CMD_OFF = 1,
+	LIGHTBAR_CMD_ON = 2,
+	LIGHTBAR_CMD_INIT = 3,
+	LIGHTBAR_CMD_BRIGHTNESS = 4,
+	LIGHTBAR_CMD_SEQ = 5,
+	LIGHTBAR_CMD_REG = 6,
+	LIGHTBAR_CMD_RGB = 7,
+	LIGHTBAR_CMD_GET_SEQ = 8,
+	LIGHTBAR_CMD_DEMO = 9,
+	LIGHTBAR_CMD_GET_PARAMS = 10,
+	LIGHTBAR_CMD_SET_PARAMS = 11,
+	LIGHTBAR_NUM_CMDS
+};
+
+/*****************************************************************************/
+/* Verified boot commands */
+
+/*
+ * Note: command code 0x29 version 0 was VBOOT_CMD in Link EVT; it may be
+ * reused for other purposes with version > 0.
+ */
+
+/* Verified boot hash command */
+#define EC_CMD_VBOOT_HASH 0x2A
+
+struct ec_params_vboot_hash {
+	uint8_t cmd;             /* enum ec_vboot_hash_cmd */
+	uint8_t hash_type;       /* enum ec_vboot_hash_type */
+	uint8_t nonce_size;      /* Nonce size; may be 0 */
+	uint8_t reserved0;       /* Reserved; set 0 */
+	uint32_t offset;         /* Offset in flash to hash */
+	uint32_t size;           /* Number of bytes to hash */
+	uint8_t nonce_data[64];  /* Nonce data; ignored if nonce_size=0 */
+} __packed;
+
+struct ec_response_vboot_hash {
+	uint8_t status;          /* enum ec_vboot_hash_status */
+	uint8_t hash_type;       /* enum ec_vboot_hash_type */
+	uint8_t digest_size;     /* Size of hash digest in bytes */
+	uint8_t reserved0;       /* Ignore; will be 0 */
+	uint32_t offset;         /* Offset in flash which was hashed */
+	uint32_t size;           /* Number of bytes hashed */
+	uint8_t hash_digest[64]; /* Hash digest data */
+} __packed;
+
+enum ec_vboot_hash_cmd {
+	EC_VBOOT_HASH_GET = 0,       /* Get current hash status */
+	EC_VBOOT_HASH_ABORT = 1,     /* Abort calculating current hash */
+	EC_VBOOT_HASH_START = 2,     /* Start computing a new hash */
+	EC_VBOOT_HASH_RECALC = 3,    /* Synchronously compute a new hash */
+};
+
+enum ec_vboot_hash_type {
+	EC_VBOOT_HASH_TYPE_SHA256 = 0, /* SHA-256 */
+};
+
+enum ec_vboot_hash_status {
+	EC_VBOOT_HASH_STATUS_NONE = 0, /* No hash (not started, or aborted) */
+	EC_VBOOT_HASH_STATUS_DONE = 1, /* Finished computing a hash */
+	EC_VBOOT_HASH_STATUS_BUSY = 2, /* Busy computing a hash */
+};
+
+/*
+ * Special values for offset for EC_VBOOT_HASH_START and EC_VBOOT_HASH_RECALC.
+ * If one of these is specified, the EC will automatically update offset and
+ * size to the correct values for the specified image (RO or RW).
+ */
+#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
+#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
+
+/*****************************************************************************/
+/* USB charging control commands */
+
+/* Set USB port charging mode */
+#define EC_CMD_USB_CHARGE_SET_MODE 0x30
+
+struct ec_params_usb_charge_set_mode {
+	uint8_t usb_port_id;
+	uint8_t mode;
+} __packed;
+
+/*****************************************************************************/
+/* Persistent storage for host */
+
+/* Maximum bytes that can be read/written in a single command */
+#define EC_PSTORE_SIZE_MAX 64
+
+/* Get persistent storage info */
+#define EC_CMD_PSTORE_INFO 0x40
+
+struct ec_response_pstore_info {
+	/* Persistent storage size, in bytes */
+	uint32_t pstore_size;
+	/* Access size; read/write offset and size must be a multiple of this */
+	uint32_t access_size;
+} __packed;
+
+/*
+ * Read persistent storage
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_PSTORE_READ 0x41
+
+struct ec_params_pstore_read {
+	uint32_t offset;   /* Byte offset to read */
+	uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Write persistent storage */
+#define EC_CMD_PSTORE_WRITE 0x42
+
+struct ec_params_pstore_write {
+	uint32_t offset;   /* Byte offset to write */
+	uint32_t size;     /* Size to write in bytes */
+	uint8_t data[EC_PSTORE_SIZE_MAX];
+} __packed;
+
+/*****************************************************************************/
+/* Real-time clock */
+
+/* RTC params and response structures */
+struct ec_params_rtc {
+	uint32_t time;
+} __packed;
+
+struct ec_response_rtc {
+	uint32_t time;
+} __packed;
+
+/* These use ec_response_rtc */
+#define EC_CMD_RTC_GET_VALUE 0x44
+#define EC_CMD_RTC_GET_ALARM 0x45
+
+/* These all use ec_params_rtc */
+#define EC_CMD_RTC_SET_VALUE 0x46
+#define EC_CMD_RTC_SET_ALARM 0x47
+
+/*****************************************************************************/
+/* Port80 log access */
+
+/* Get last port80 code from previous boot */
+#define EC_CMD_PORT80_LAST_BOOT 0x48
+
+struct ec_response_port80_last_boot {
+	uint16_t code;
+} __packed;
+
+/*****************************************************************************/
+/* Thermal engine commands */
+
+/* Set thershold value */
+#define EC_CMD_THERMAL_SET_THRESHOLD 0x50
+
+struct ec_params_thermal_set_threshold {
+	uint8_t sensor_type;
+	uint8_t threshold_id;
+	uint16_t value;
+} __packed;
+
+/* Get threshold value */
+#define EC_CMD_THERMAL_GET_THRESHOLD 0x51
+
+struct ec_params_thermal_get_threshold {
+	uint8_t sensor_type;
+	uint8_t threshold_id;
+} __packed;
+
+struct ec_response_thermal_get_threshold {
+	uint16_t value;
+} __packed;
+
+/* Toggle automatic fan control */
+#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52
+
+/* Get TMP006 calibration data */
+#define EC_CMD_TMP006_GET_CALIBRATION 0x53
+
+struct ec_params_tmp006_get_calibration {
+	uint8_t index;
+} __packed;
+
+struct ec_response_tmp006_get_calibration {
+	float s0;
+	float b0;
+	float b1;
+	float b2;
+} __packed;
+
+/* Set TMP006 calibration data */
+#define EC_CMD_TMP006_SET_CALIBRATION 0x54
+
+struct ec_params_tmp006_set_calibration {
+	uint8_t index;
+	uint8_t reserved[3];  /* Reserved; set 0 */
+	float s0;
+	float b0;
+	float b1;
+	float b2;
+} __packed;
+
+/*****************************************************************************/
+/* CROS_EC - Matrix KeyBoard Protocol */
+
+/*
+ * Read key state
+ *
+ * Returns raw data for keyboard cols; see ec_response_cros_ec_info.cols for
+ * expected response size.
+ */
+#define EC_CMD_CROS_EC_STATE 0x60
+
+/* Provide information about the matrix : number of rows and columns */
+#define EC_CMD_CROS_EC_INFO 0x61
+
+struct ec_response_cros_ec_info {
+	uint32_t rows;
+	uint32_t cols;
+	uint8_t switches;
+} __packed;
+
+/* Simulate key press */
+#define EC_CMD_CROS_EC_SIMULATE_KEY 0x62
+
+struct ec_params_cros_ec_simulate_key {
+	uint8_t col;
+	uint8_t row;
+	uint8_t pressed;
+} __packed;
+
+/* Configure keyboard scanning */
+#define EC_CMD_CROS_EC_SET_CONFIG 0x64
+#define EC_CMD_CROS_EC_GET_CONFIG 0x65
+
+/* flags */
+enum cros_ec_config_flags {
+	EC_CROS_EC_FLAGS_ENABLE = 1,	/* Enable keyboard scanning */
+};
+
+enum cros_ec_config_valid {
+	EC_CROS_EC_VALID_SCAN_PERIOD		= 1 << 0,
+	EC_CROS_EC_VALID_POLL_TIMEOUT		= 1 << 1,
+	EC_CROS_EC_VALID_MIN_POST_SCAN_DELAY	= 1 << 3,
+	EC_CROS_EC_VALID_OUTPUT_SETTLE		= 1 << 4,
+	EC_CROS_EC_VALID_DEBOUNCE_DOWN		= 1 << 5,
+	EC_CROS_EC_VALID_DEBOUNCE_UP		= 1 << 6,
+	EC_CROS_EC_VALID_FIFO_MAX_DEPTH		= 1 << 7,
+};
+
+/* Configuration for our key scanning algorithm */
+struct ec_cros_ec_config {
+	uint32_t valid_mask;		/* valid fields */
+	uint8_t flags;		/* some flags (enum cros_ec_config_flags) */
+	uint8_t valid_flags;		/* which flags are valid */
+	uint16_t scan_period_us;	/* period between start of scans */
+	/* revert to interrupt mode after no activity for this long */
+	uint32_t poll_timeout_us;
+	/*
+	 * minimum post-scan relax time. Once we finish a scan we check
+	 * the time until we are due to start the next one. If this time is
+	 * shorter this field, we use this instead.
+	 */
+	uint16_t min_post_scan_delay_us;
+	/* delay between setting up output and waiting for it to settle */
+	uint16_t output_settle_us;
+	uint16_t debounce_down_us;	/* time for debounce on key down */
+	uint16_t debounce_up_us;	/* time for debounce on key up */
+	/* maximum depth to allow for fifo (0 = no keyscan output) */
+	uint8_t fifo_max_depth;
+} __packed;
+
+struct ec_params_cros_ec_set_config {
+	struct ec_cros_ec_config config;
+} __packed;
+
+struct ec_response_cros_ec_get_config {
+	struct ec_cros_ec_config config;
+} __packed;
+
+/* Run the key scan emulation */
+#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66
+
+enum ec_keyscan_seq_cmd {
+	EC_KEYSCAN_SEQ_STATUS = 0,	/* Get status information */
+	EC_KEYSCAN_SEQ_CLEAR = 1,	/* Clear sequence */
+	EC_KEYSCAN_SEQ_ADD = 2,		/* Add item to sequence */
+	EC_KEYSCAN_SEQ_START = 3,	/* Start running sequence */
+	EC_KEYSCAN_SEQ_COLLECT = 4,	/* Collect sequence summary data */
+};
+
+enum ec_collect_flags {
+	/*
+	 * Indicates this scan was processed by the EC. Due to timing, some
+	 * scans may be skipped.
+	 */
+	EC_KEYSCAN_SEQ_FLAG_DONE	= 1 << 0,
+};
+
+struct ec_collect_item {
+	uint8_t flags;		/* some flags (enum ec_collect_flags) */
+};
+
+struct ec_params_keyscan_seq_ctrl {
+	uint8_t cmd;	/* Command to send (enum ec_keyscan_seq_cmd) */
+	union {
+		struct {
+			uint8_t active;		/* still active */
+			uint8_t num_items;	/* number of items */
+			/* Current item being presented */
+			uint8_t cur_item;
+		} status;
+		struct {
+			/*
+			 * Absolute time for this scan, measured from the
+			 * start of the sequence.
+			 */
+			uint32_t time_us;
+			uint8_t scan[0];	/* keyscan data */
+		} add;
+		struct {
+			uint8_t start_item;	/* First item to return */
+			uint8_t num_items;	/* Number of items to return */
+		} collect;
+	};
+} __packed;
+
+struct ec_result_keyscan_seq_ctrl {
+	union {
+		struct {
+			uint8_t num_items;	/* Number of items */
+			/* Data for each item */
+			struct ec_collect_item item[0];
+		} collect;
+	};
+} __packed;
+
+/*****************************************************************************/
+/* Temperature sensor commands */
+
+/* Read temperature sensor info */
+#define EC_CMD_TEMP_SENSOR_GET_INFO 0x70
+
+struct ec_params_temp_sensor_get_info {
+	uint8_t id;
+} __packed;
+
+struct ec_response_temp_sensor_get_info {
+	char sensor_name[32];
+	uint8_t sensor_type;
+} __packed;
+
+/*****************************************************************************/
+
+/*
+ * Note: host commands 0x80 - 0x87 are reserved to avoid conflict with ACPI
+ * commands accidentally sent to the wrong interface.  See the ACPI section
+ * below.
+ */
+
+/*****************************************************************************/
+/* Host event commands */
+
+/*
+ * Host event mask params and response structures, shared by all of the host
+ * event commands below.
+ */
+struct ec_params_host_event_mask {
+	uint32_t mask;
+} __packed;
+
+struct ec_response_host_event_mask {
+	uint32_t mask;
+} __packed;
+
+/* These all use ec_response_host_event_mask */
+#define EC_CMD_HOST_EVENT_GET_B         0x87
+#define EC_CMD_HOST_EVENT_GET_SMI_MASK  0x88
+#define EC_CMD_HOST_EVENT_GET_SCI_MASK  0x89
+#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x8d
+
+/* These all use ec_params_host_event_mask */
+#define EC_CMD_HOST_EVENT_SET_SMI_MASK  0x8a
+#define EC_CMD_HOST_EVENT_SET_SCI_MASK  0x8b
+#define EC_CMD_HOST_EVENT_CLEAR         0x8c
+#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x8e
+#define EC_CMD_HOST_EVENT_CLEAR_B       0x8f
+
+/*****************************************************************************/
+/* Switch commands */
+
+/* Enable/disable LCD backlight */
+#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x90
+
+struct ec_params_switch_enable_backlight {
+	uint8_t enabled;
+} __packed;
+
+/* Enable/disable WLAN/Bluetooth */
+#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91
+
+struct ec_params_switch_enable_wireless {
+	uint8_t enabled;
+} __packed;
+
+/*****************************************************************************/
+/* GPIO commands. Only available on EC if write protect has been disabled. */
+
+/* Set GPIO output value */
+#define EC_CMD_GPIO_SET 0x92
+
+struct ec_params_gpio_set {
+	char name[32];
+	uint8_t val;
+} __packed;
+
+/* Get GPIO value */
+#define EC_CMD_GPIO_GET 0x93
+
+struct ec_params_gpio_get {
+	char name[32];
+} __packed;
+struct ec_response_gpio_get {
+	uint8_t val;
+} __packed;
+
+/*****************************************************************************/
+/* I2C commands. Only available when flash write protect is unlocked. */
+
+/* Read I2C bus */
+#define EC_CMD_I2C_READ 0x94
+
+struct ec_params_i2c_read {
+	uint16_t addr;
+	uint8_t read_size; /* Either 8 or 16. */
+	uint8_t port;
+	uint8_t offset;
+} __packed;
+struct ec_response_i2c_read {
+	uint16_t data;
+} __packed;
+
+/* Write I2C bus */
+#define EC_CMD_I2C_WRITE 0x95
+
+struct ec_params_i2c_write {
+	uint16_t data;
+	uint16_t addr;
+	uint8_t write_size; /* Either 8 or 16. */
+	uint8_t port;
+	uint8_t offset;
+} __packed;
+
+/*****************************************************************************/
+/* Charge state commands. Only available when flash write protect unlocked. */
+
+/* Force charge state machine to stop in idle mode */
+#define EC_CMD_CHARGE_FORCE_IDLE 0x96
+
+struct ec_params_force_idle {
+	uint8_t enabled;
+} __packed;
+
+/*****************************************************************************/
+/* Console commands. Only available when flash write protect is unlocked. */
+
+/* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */
+#define EC_CMD_CONSOLE_SNAPSHOT 0x97
+
+/*
+ * Read next chunk of data from saved snapshot.
+ *
+ * Response is null-terminated string.  Empty string, if there is no more
+ * remaining output.
+ */
+#define EC_CMD_CONSOLE_READ 0x98
+
+/*****************************************************************************/
+
+/*
+ * Cut off battery power output if the battery supports.
+ *
+ * For unsupported battery, just don't implement this command and lets EC
+ * return EC_RES_INVALID_COMMAND.
+ */
+#define EC_CMD_BATTERY_CUT_OFF 0x99
+
+/*****************************************************************************/
+/* USB port mux control. */
+
+/*
+ * Switch USB mux or return to automatic switching.
+ */
+#define EC_CMD_USB_MUX 0x9a
+
+struct ec_params_usb_mux {
+	uint8_t mux;
+} __packed;
+
+/*****************************************************************************/
+/* LDOs / FETs control. */
+
+enum ec_ldo_state {
+	EC_LDO_STATE_OFF = 0,	/* the LDO / FET is shut down */
+	EC_LDO_STATE_ON = 1,	/* the LDO / FET is ON / providing power */
+};
+
+/*
+ * Switch on/off a LDO.
+ */
+#define EC_CMD_LDO_SET 0x9b
+
+struct ec_params_ldo_set {
+	uint8_t index;
+	uint8_t state;
+} __packed;
+
+/*
+ * Get LDO state.
+ */
+#define EC_CMD_LDO_GET 0x9c
+
+struct ec_params_ldo_get {
+	uint8_t index;
+} __packed;
+
+struct ec_response_ldo_get {
+	uint8_t state;
+} __packed;
+
+/*****************************************************************************/
+/* Temporary debug commands. TODO: remove this crosbug.com/p/13849 */
+
+/*
+ * Dump charge state machine context.
+ *
+ * Response is a binary dump of charge state machine context.
+ */
+#define EC_CMD_CHARGE_DUMP 0xa0
+
+/*
+ * Set maximum battery charging current.
+ */
+#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1
+
+struct ec_params_current_limit {
+	uint32_t limit;
+} __packed;
+
+/*****************************************************************************/
+/* Smart battery pass-through */
+
+/* Get / Set 16-bit smart battery registers */
+#define EC_CMD_SB_READ_WORD   0xb0
+#define EC_CMD_SB_WRITE_WORD  0xb1
+
+/* Get / Set string smart battery parameters
+ * formatted as SMBUS "block".
+ */
+#define EC_CMD_SB_READ_BLOCK  0xb2
+#define EC_CMD_SB_WRITE_BLOCK 0xb3
+
+struct ec_params_sb_rd {
+	uint8_t reg;
+} __packed;
+
+struct ec_response_sb_rd_word {
+	uint16_t value;
+} __packed;
+
+struct ec_params_sb_wr_word {
+	uint8_t reg;
+	uint16_t value;
+} __packed;
+
+struct ec_response_sb_rd_block {
+	uint8_t data[32];
+} __packed;
+
+struct ec_params_sb_wr_block {
+	uint8_t reg;
+	uint16_t data[32];
+} __packed;
+
+/*****************************************************************************/
+/* System commands */
+
+/*
+ * TODO: this is a confusing name, since it doesn't necessarily reboot the EC.
+ * Rename to "set image" or something similar.
+ */
+#define EC_CMD_REBOOT_EC 0xd2
+
+/* Command */
+enum ec_reboot_cmd {
+	EC_REBOOT_CANCEL = 0,        /* Cancel a pending reboot */
+	EC_REBOOT_JUMP_RO = 1,       /* Jump to RO without rebooting */
+	EC_REBOOT_JUMP_RW = 2,       /* Jump to RW without rebooting */
+	/* (command 3 was jump to RW-B) */
+	EC_REBOOT_COLD = 4,          /* Cold-reboot */
+	EC_REBOOT_DISABLE_JUMP = 5,  /* Disable jump until next reboot */
+	EC_REBOOT_HIBERNATE = 6      /* Hibernate EC */
+};
+
+/* Flags for ec_params_reboot_ec.reboot_flags */
+#define EC_REBOOT_FLAG_RESERVED0      (1 << 0)  /* Was recovery request */
+#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1)  /* Reboot after AP shutdown */
+
+struct ec_params_reboot_ec {
+	uint8_t cmd;           /* enum ec_reboot_cmd */
+	uint8_t flags;         /* See EC_REBOOT_FLAG_* */
+} __packed;
+
+/*
+ * Get information on last EC panic.
+ *
+ * Returns variable-length platform-dependent panic information.  See panic.h
+ * for details.
+ */
+#define EC_CMD_GET_PANIC_INFO 0xd3
+
+/*****************************************************************************/
+/*
+ * ACPI commands
+ *
+ * These are valid ONLY on the ACPI command/data port.
+ */
+
+/*
+ * ACPI Read Embedded Controller
+ *
+ * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*).
+ *
+ * Use the following sequence:
+ *
+ *    - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write address to EC_LPC_ADDR_ACPI_DATA
+ *    - Wait for EC_LPC_CMDR_DATA bit to set
+ *    - Read value from EC_LPC_ADDR_ACPI_DATA
+ */
+#define EC_CMD_ACPI_READ 0x80
+
+/*
+ * ACPI Write Embedded Controller
+ *
+ * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*).
+ *
+ * Use the following sequence:
+ *
+ *    - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write address to EC_LPC_ADDR_ACPI_DATA
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write value to EC_LPC_ADDR_ACPI_DATA
+ */
+#define EC_CMD_ACPI_WRITE 0x81
+
+/*
+ * ACPI Query Embedded Controller
+ *
+ * This clears the lowest-order bit in the currently pending host events, and
+ * sets the result code to the 1-based index of the bit (event 0x00000001 = 1,
+ * event 0x80000000 = 32), or 0 if no event was pending.
+ */
+#define EC_CMD_ACPI_QUERY_EVENT 0x84
+
+/* Valid addresses in ACPI memory space, for read/write commands */
+/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */
+#define EC_ACPI_MEM_VERSION            0x00
+/*
+ * Test location; writing value here updates test compliment byte to (0xff -
+ * value).
+ */
+#define EC_ACPI_MEM_TEST               0x01
+/* Test compliment; writes here are ignored. */
+#define EC_ACPI_MEM_TEST_COMPLIMENT    0x02
+/* Keyboard backlight brightness percent (0 - 100) */
+#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03
+
+/* Current version of ACPI memory address space */
+#define EC_ACPI_MEM_VERSION_CURRENT 1
+
+
+/*****************************************************************************/
+/*
+ * Special commands
+ *
+ * These do not follow the normal rules for commands.  See each command for
+ * details.
+ */
+
+/*
+ * Reboot NOW
+ *
+ * This command will work even when the EC LPC interface is busy, because the
+ * reboot command is processed at interrupt level.  Note that when the EC
+ * reboots, the host will reboot too, so there is no response to this command.
+ *
+ * Use EC_CMD_REBOOT_EC to reboot the EC more politely.
+ */
+#define EC_CMD_REBOOT 0xd1  /* Think "die" */
+
+/*
+ * Resend last response (not supported on LPC).
+ *
+ * Returns EC_RES_UNAVAILABLE if there is no response available - for example,
+ * there was no previous command, or the previous command's response was too
+ * big to save.
+ */
+#define EC_CMD_RESEND_RESPONSE 0xdb
+
+/*
+ * This header byte on a command indicate version 0. Any header byte less
+ * than this means that we are talking to an old EC which doesn't support
+ * versioning. In that case, we assume version 0.
+ *
+ * Header bytes greater than this indicate a later version. For example,
+ * EC_CMD_VERSION0 + 1 means we are using version 1.
+ *
+ * The old EC interface must not use commands 0dc or higher.
+ */
+#define EC_CMD_VERSION0 0xdc
+
+#endif  /* !__ACPI__ */
+
+#endif  /* __CROS_EC_COMMANDS_H */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 1ece612..d93e102 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -84,11 +84,14 @@
 	COMPAT_SAMSUNG_EXYNOS5_SOUND,	/* Exynos Sound */
 	COMPAT_WOLFSON_WM8994_CODEC,	/* Wolfson WM8994 Sound Codec */
 	COMPAT_SAMSUNG_EXYNOS_SPI,	/* Exynos SPI */
+	COMPAT_GOOGLE_CROS_EC,		/* Google CROS_EC Protocol */
+	COMPAT_GOOGLE_CROS_EC_KEYB,	/* Google CROS_EC Keyboard */
 	COMPAT_SAMSUNG_EXYNOS_EHCI,	/* Exynos EHCI controller */
 	COMPAT_SAMSUNG_EXYNOS_USB_PHY,	/* Exynos phy controller for usb2.0 */
 	COMPAT_SAMSUNG_EXYNOS_TMU,	/* Exynos TMU */
 	COMPAT_SAMSUNG_EXYNOS_FIMD,	/* Exynos Display controller */
 	COMPAT_SAMSUNG_EXYNOS5_DP,	/* Exynos Display port controller */
+	COMPAT_SAMSUNG_EXYNOS5_DWMMC,	/* Exynos5 DWMMC controller */
 	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */
 	COMPAT_GENERIC_SPI_FLASH,	/* Generic SPI Flash chip */
 	COMPAT_MAXIM_98095_CODEC,	/* MAX98095 Codec */
diff --git a/include/ide.h b/include/ide.h
index afea85c..f691a74 100644
--- a/include/ide.h
+++ b/include/ide.h
@@ -54,8 +54,9 @@
  */
 
 void ide_init(void);
-ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer);
-ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer);
+ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer);
+ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt,
+		const void *buffer);
 
 #ifdef CONFIG_IDE_PREINIT
 int ide_preinit(void);
diff --git a/include/image.h b/include/image.h
index 8ccc00b..a7b93db 100644
--- a/include/image.h
+++ b/include/image.h
@@ -320,13 +320,16 @@
 	int		verify;		/* getenv("verify")[0] != 'n' */
 
 #define	BOOTM_STATE_START	(0x00000001)
-#define	BOOTM_STATE_LOADOS	(0x00000002)
-#define	BOOTM_STATE_RAMDISK	(0x00000004)
-#define	BOOTM_STATE_FDT		(0x00000008)
-#define	BOOTM_STATE_OS_CMDLINE	(0x00000010)
-#define	BOOTM_STATE_OS_BD_T	(0x00000020)
-#define	BOOTM_STATE_OS_PREP	(0x00000040)
-#define	BOOTM_STATE_OS_GO	(0x00000080)
+#define	BOOTM_STATE_FINDOS	(0x00000002)
+#define	BOOTM_STATE_FINDOTHER	(0x00000004)
+#define	BOOTM_STATE_LOADOS	(0x00000008)
+#define	BOOTM_STATE_RAMDISK	(0x00000010)
+#define	BOOTM_STATE_FDT		(0x00000020)
+#define	BOOTM_STATE_OS_CMDLINE	(0x00000040)
+#define	BOOTM_STATE_OS_BD_T	(0x00000080)
+#define	BOOTM_STATE_OS_PREP	(0x00000100)
+#define	BOOTM_STATE_OS_FAKE_GO	(0x00000200)	/* 'Almost' run the OS */
+#define	BOOTM_STATE_OS_GO	(0x00000400)
 	int		state;
 
 #ifdef CONFIG_LMB
@@ -667,11 +670,12 @@
 #define FIT_IMAGES_PATH		"/images"
 #define FIT_CONFS_PATH		"/configurations"
 
-/* hash node */
+/* hash/signature node */
 #define FIT_HASH_NODENAME	"hash"
 #define FIT_ALGO_PROP		"algo"
 #define FIT_VALUE_PROP		"value"
 #define FIT_IGNORE_PROP		"uboot-ignore"
+#define FIT_SIG_NODENAME	"signature"
 
 /* image node */
 #define FIT_DATA_PROP		"data"
@@ -759,12 +763,26 @@
 int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
 
 /**
- * fit_add_verification_data() - Calculate and add hashes to FIT
+ * fit_add_verification_data() - add verification data to FIT image nodes
  *
- * @fit:	Fit image to process
- * @return 0 if ok, <0 for error
+ * @keydir:	Directory containing keys
+ * @kwydest:	FDT blob to write public key information to
+ * @fit:	Pointer to the FIT format image header
+ * @comment:	Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ *
+ * Adds hash values for all component images in the FIT blob.
+ * Hashes are calculated for all component images which have hash subnodes
+ * with algorithm property set to one of the supported hash algorithms.
+ *
+ * Also add signatures if signature nodes are present.
+ *
+ * returns
+ *     0, on success
+ *     libfdt error code, on failure
  */
-int fit_add_verification_data(void *fit);
+int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+			      const char *comment, int require_keys);
 
 int fit_image_verify(const void *fit, int noffset);
 int fit_config_verify(const void *fit, int conf_noffset);
@@ -801,15 +819,19 @@
 			uint8_t *value, int *value_len);
 
 /*
- * At present we only support verification on the device
+ * At present we only support signing on the host, and verification on the
+ * device
  */
 #if defined(CONFIG_FIT_SIGNATURE)
 # ifdef USE_HOSTCC
+#  define IMAGE_ENABLE_SIGN	1
 #  define IMAGE_ENABLE_VERIFY	0
 #else
+#  define IMAGE_ENABLE_SIGN	0
 #  define IMAGE_ENABLE_VERIFY	1
 # endif
 #else
+# define IMAGE_ENABLE_SIGN	0
 # define IMAGE_ENABLE_VERIFY	0
 #endif
 
@@ -825,6 +847,137 @@
 #define IMAGE_ENABLE_BEST_MATCH	0
 #endif
 
+/* Information passed to the signing routines */
+struct image_sign_info {
+	const char *keydir;		/* Directory conaining keys */
+	const char *keyname;		/* Name of key to use */
+	void *fit;			/* Pointer to FIT blob */
+	int node_offset;		/* Offset of signature node */
+	struct image_sig_algo *algo;	/* Algorithm information */
+	const void *fdt_blob;		/* FDT containing public keys */
+	int required_keynode;		/* Node offset of key to use: -1=any */
+	const char *require_keys;	/* Value for 'required' property */
+};
+
+/* A part of an image, used for hashing */
+struct image_region {
+	const void *data;
+	int size;
+};
+
+struct image_sig_algo {
+	const char *name;		/* Name of algorithm */
+
+	/**
+	 * sign() - calculate and return signature for given input data
+	 *
+	 * @info:	Specifies key and FIT information
+	 * @data:	Pointer to the input data
+	 * @data_len:	Data length
+	 * @sigp:	Set to an allocated buffer holding the signature
+	 * @sig_len:	Set to length of the calculated hash
+	 *
+	 * This computes input data signature according to selected algorithm.
+	 * Resulting signature value is placed in an allocated buffer, the
+	 * pointer is returned as *sigp. The length of the calculated
+	 * signature is returned via the sig_len pointer argument. The caller
+	 * should free *sigp.
+	 *
+	 * @return: 0, on success, -ve on error
+	 */
+	int (*sign)(struct image_sign_info *info,
+		    const struct image_region region[],
+		    int region_count, uint8_t **sigp, uint *sig_len);
+
+	/**
+	 * add_verify_data() - Add verification information to FDT
+	 *
+	 * Add public key information to the FDT node, suitable for
+	 * verification at run-time. The information added depends on the
+	 * algorithm being used.
+	 *
+	 * @info:	Specifies key and FIT information
+	 * @keydest:	Destination FDT blob for public key data
+	 * @return: 0, on success, -ve on error
+	 */
+	int (*add_verify_data)(struct image_sign_info *info, void *keydest);
+
+	/**
+	 * verify() - Verify a signature against some data
+	 *
+	 * @info:	Specifies key and FIT information
+	 * @data:	Pointer to the input data
+	 * @data_len:	Data length
+	 * @sig:	Signature
+	 * @sig_len:	Number of bytes in signature
+	 * @return 0 if verified, -ve on error
+	 */
+	int (*verify)(struct image_sign_info *info,
+		      const struct image_region region[], int region_count,
+		      uint8_t *sig, uint sig_len);
+};
+
+/**
+ * image_get_sig_algo() - Look up a signature algortihm
+ *
+ * @param name		Name of algorithm
+ * @return pointer to algorithm information, or NULL if not found
+ */
+struct image_sig_algo *image_get_sig_algo(const char *name);
+
+/**
+ * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
+ *
+ * @fit:		FIT to check
+ * @image_noffset:	Offset of image node to check
+ * @data:		Image data to check
+ * @size:		Size of image data
+ * @sig_blob:		FDT containing public keys
+ * @no_sigsp:		Returns 1 if no signatures were required, and
+ *			therefore nothing was checked. The caller may wish
+ *			to fall back to other mechanisms, or refuse to
+ *			boot.
+ * @return 0 if all verified ok, <0 on error
+ */
+int fit_image_verify_required_sigs(const void *fit, int image_noffset,
+		const char *data, size_t size, const void *sig_blob,
+		int *no_sigsp);
+
+/**
+ * fit_image_check_sig() - Check a single image signature node
+ *
+ * @fit:		FIT to check
+ * @noffset:		Offset of signature node to check
+ * @data:		Image data to check
+ * @size:		Size of image data
+ * @required_keynode:	Offset in the control FDT of the required key node,
+ *			if any. If this is given, then the image wil not
+ *			pass verification unless that key is used. If this is
+ *			-1 then any signature will do.
+ * @err_msgp:		In the event of an error, this will be pointed to a
+ *			help error string to display to the user.
+ * @return 0 if all verified ok, <0 on error
+ */
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+		size_t size, int required_keynode, char **err_msgp);
+
+/**
+ * fit_region_make_list() - Make a list of regions to hash
+ *
+ * Given a list of FIT regions (offset, size) provided by libfdt, create
+ * a list of regions (void *, size) for use by the signature creationg
+ * and verification code.
+ *
+ * @fit:		FIT image to process
+ * @fdt_regions:	Regions as returned by libfdt
+ * @count:		Number of regions returned by libfdt
+ * @region:		Place to put list of regions (NULL to allocate it)
+ * @return pointer to list of regions, or NULL if out of memory
+ */
+struct image_region *fit_region_make_list(const void *fit,
+		struct fdt_region *fdt_regions, int count,
+		struct image_region *region);
+
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
 	return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT);
diff --git a/include/libfdt.h b/include/libfdt.h
index c5ec2ac..765d84f 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1511,4 +1511,68 @@
 
 const char *fdt_strerror(int errval);
 
+struct fdt_region {
+	int offset;
+	int size;
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing at all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt:	Device tree to check
+ * @inc:	List of node paths to included
+ * @inc_count:	Number of node paths in list
+ * @exc_prop:	List of properties names to exclude
+ * @exc_prop_count:	Number of properties in exclude list
+ * @region:	Returns list of regions
+ * @max_region:	Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @add_string_tab:	1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+		     char * const exc_prop[], int exc_prop_count,
+		     struct fdt_region region[], int max_regions,
+		     char *path, int path_len, int add_string_tab);
+
 #endif /* _LIBFDT_H */
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index fcb20fe..f6dbdb0 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -580,6 +580,8 @@
 #define SUPPORTED_10000baseKX4_Full	(1 << 18)
 #define SUPPORTED_10000baseKR_Full	(1 << 19)
 #define SUPPORTED_10000baseR_FEC	(1 << 20)
+#define SUPPORTED_1000baseX_Half	(1 << 21)
+#define SUPPORTED_1000baseX_Full	(1 << 22)
 
 /* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half		(1 << 0)
@@ -603,6 +605,8 @@
 #define ADVERTISED_10000baseKX4_Full	(1 << 18)
 #define ADVERTISED_10000baseKR_Full	(1 << 19)
 #define ADVERTISED_10000baseR_FEC	(1 << 20)
+#define ADVERTISED_1000baseX_Half	(1 << 21)
+#define ADVERTISED_1000baseX_Full	(1 << 22)
 
 /* The following are all involved in forcing a particular link
  * mode for the device for setting things.  When getting the
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 8b92692..66b83d8 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -115,6 +115,8 @@
 #define EXPANSION_MFAULTS	0x0010	/* Multiple faults detected    */
 #define EXPANSION_RESV		0xffe0	/* Unused...		       */
 
+#define ESTATUS_1000_XFULL	0x8000	/* Can do 1000BX Full */
+#define ESTATUS_1000_XHALF	0x4000	/* Can do 1000BX Half */
 #define ESTATUS_1000_TFULL	0x2000	/* Can do 1000BT Full */
 #define ESTATUS_1000_THALF	0x1000	/* Can do 1000BT Half */
 
diff --git a/include/micrel.h b/include/micrel.h
index 25e8a46..e1c62d8 100644
--- a/include/micrel.h
+++ b/include/micrel.h
@@ -8,9 +8,20 @@
 #define MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW	0x105
 #define MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW	0x106
 #define MII_KSZ9021_EXT_ANALOG_TEST		0x107
+/* Register operations */
+#define MII_KSZ9031_MOD_REG			0x0000
+/* Data operations */
+#define MII_KSZ9031_MOD_DATA_NO_POST_INC	0x4000
+#define MII_KSZ9031_MOD_DATA_POST_INC_RW	0x8000
+#define MII_KSZ9031_MOD_DATA_POST_INC_W		0xC000
 
 struct phy_device;
 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val);
 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum);
 
+int ksz9031_phy_extended_write(struct phy_device *phydev, int devaddr,
+			       int regnum, u16 mode, u16 val);
+int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
+			      int regnum, u16 mode);
+
 #endif
diff --git a/include/mmc.h b/include/mmc.h
index ea198d8..583c30e 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -93,6 +93,11 @@
 #define MMC_CMD_APP_CMD			55
 #define MMC_CMD_SPI_READ_OCR		58
 #define MMC_CMD_SPI_CRC_ON_OFF		59
+#define MMC_CMD_RES_MAN			62
+
+#define MMC_CMD62_ARG1			0xefac62ec
+#define MMC_CMD62_ARG2			0xcbaea7
+
 
 #define SD_CMD_SEND_RELATIVE_ADDR	3
 #define SD_CMD_SWITCH_FUNC		6
@@ -162,6 +167,7 @@
 #define EXT_CSD_PARTITIONING_SUPPORT	160	/* RO */
 #define EXT_CSD_RPMB_MULT		168	/* RO */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
+#define EXT_CSD_BOOT_BUS_WIDTH		177
 #define EXT_CSD_PART_CONF		179	/* R/W */
 #define EXT_CSD_BUS_WIDTH		183	/* R/W */
 #define EXT_CSD_HS_TIMING		185	/* R/W */
@@ -187,6 +193,16 @@
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
 #define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
 
+#define EXT_CSD_BOOT_ACK_ENABLE			(1 << 6)
+#define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3)
+#define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0)
+#define EXT_CSD_PARTITION_ACCESS_DISABLE	(0 << 0)
+
+#define EXT_CSD_BOOT_ACK(x)		(x << 6)
+#define EXT_CSD_BOOT_PART_NUM(x)	(x << 3)
+#define EXT_CSD_PARTITION_ACCESS(x)	(x << 0)
+
+
 #define R1_ILLEGAL_COMMAND		(1 << 22)
 #define R1_APP_CMD			(1 << 5)
 
@@ -214,6 +230,11 @@
 /* Maximum block size for MMC */
 #define MMC_MAX_BLOCK_LEN	512
 
+/* The number of MMC physical partitions.  These consist of:
+ * boot partitions (2), general purpose partitions (4) in MMC v4.4.
+ */
+#define MMC_NUM_BOOT_PARTITION	2
+
 struct mmc_cid {
 	unsigned long psn;
 	unsigned short oid;
@@ -298,6 +319,11 @@
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 void spl_mmc_load(void) __noreturn;
+/* Function to change the size of boot partition and rpmb partitions */
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+					unsigned long rpmbsize);
+/* Function to send commands to open/close the specified boot partition */
+int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
 
 /**
  * Start device initialization and return immediately; it does not block on
diff --git a/include/net.h b/include/net.h
index 23fb947..7673470 100644
--- a/include/net.h
+++ b/include/net.h
@@ -39,7 +39,7 @@
 #define PKTALIGN	ARCH_DMA_MINALIGN
 
 /* IPv4 addresses are always 32 bits in size */
-typedef u32		IPaddr_t;
+typedef __be32		IPaddr_t;
 
 
 /**
diff --git a/include/netdev.h b/include/netdev.h
index df454b5..917d874 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -67,10 +67,12 @@
 int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr);
 int ftgmac100_initialize(bd_t *bits);
 int ftmac100_initialize(bd_t *bits);
+int ftmac110_initialize(bd_t *bits);
 int greth_initialize(bd_t *bis);
 void gt6426x_eth_initialize(bd_t *bis);
 int inca_switch_initialize(bd_t *bis);
 int ks8695_eth_initialize(void);
+int ks8851_mll_initialize(u8 dev_num, int base_addr);
 int lan91c96_initialize(u8 dev_num, int base_addr);
 int macb_eth_initialize(int id, void *regs, unsigned int phy_addr);
 int mcdmafec_initialize(bd_t *bis);
@@ -93,6 +95,7 @@
 int skge_initialize(bd_t *bis);
 int smc91111_initialize(u8 dev_num, int base_addr);
 int smc911x_initialize(u8 dev_num, int base_addr);
+int sunxi_wemac_initialize(bd_t *bis);
 int tsi108_eth_initialize(bd_t *bis);
 int uec_standard_init(bd_t *bis);
 int uli526x_initialize(bd_t *bis);
diff --git a/include/part.h b/include/part.h
index f7c7cc5..35c1c5b 100644
--- a/include/part.h
+++ b/include/part.h
@@ -43,15 +43,15 @@
 	char		product[20+1];	/* IDE Serial no, SCSI product */
 	char		revision[8+1];	/* firmware revision */
 	unsigned long	(*block_read)(int dev,
-				      unsigned long start,
+				      lbaint_t start,
 				      lbaint_t blkcnt,
 				      void *buffer);
 	unsigned long	(*block_write)(int dev,
-				       unsigned long start,
+				       lbaint_t start,
 				       lbaint_t blkcnt,
 				       const void *buffer);
 	unsigned long   (*block_erase)(int dev,
-				       unsigned long start,
+				       lbaint_t start,
 				       lbaint_t blkcnt);
 	void		*priv;		/* driver private struct pointer */
 }block_dev_desc_t;
diff --git a/include/pci.h b/include/pci.h
index f9c5148..98ba151 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -462,7 +462,7 @@
 #define PCI_REGION_SYS_MEMORY	0x00000100	/* System memory */
 #define PCI_REGION_RO		0x00000200	/* Read-only memory */
 
-extern __inline__ void pci_set_region(struct pci_region *reg,
+static inline void pci_set_region(struct pci_region *reg,
 				      pci_addr_t bus_start,
 				      phys_addr_t phys_start,
 				      pci_size_t size,
@@ -548,7 +548,7 @@
 	void *priv_data;
 };
 
-extern __inline__ void pci_set_ops(struct pci_controller *hose,
+static inline void pci_set_ops(struct pci_controller *hose,
 				   int (*read_byte)(struct pci_controller*,
 						    pci_dev_t, int where, u8 *),
 				   int (*read_word)(struct pci_controller*,
diff --git a/include/phy.h b/include/phy.h
index 75bf3b4..dbf3274 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -214,6 +214,7 @@
 int genphy_config_aneg(struct phy_device *phydev);
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_update_link(struct phy_device *phydev);
+int genphy_parse_link(struct phy_device *phydev);
 int genphy_config(struct phy_device *phydev);
 int genphy_startup(struct phy_device *phydev);
 int genphy_shutdown(struct phy_device *phydev);
diff --git a/include/rsa.h b/include/rsa.h
new file mode 100644
index 0000000..a5dd676
--- /dev/null
+++ b/include/rsa.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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
+ */
+
+#ifndef _RSA_H
+#define _RSA_H
+
+#include <errno.h>
+#include <image.h>
+
+#if IMAGE_ENABLE_SIGN
+/**
+ * sign() - calculate and return signature for given input data
+ *
+ * @info:	Specifies key and FIT information
+ * @data:	Pointer to the input data
+ * @data_len:	Data length
+ * @sigp:	Set to an allocated buffer holding the signature
+ * @sig_len:	Set to length of the calculated hash
+ *
+ * This computes input data signature according to selected algorithm.
+ * Resulting signature value is placed in an allocated buffer, the
+ * pointer is returned as *sigp. The length of the calculated
+ * signature is returned via the sig_len pointer argument. The caller
+ * should free *sigp.
+ *
+ * @return: 0, on success, -ve on error
+ */
+int rsa_sign(struct image_sign_info *info,
+	     const struct image_region region[],
+	     int region_count, uint8_t **sigp, uint *sig_len);
+
+/**
+ * add_verify_data() - Add verification information to FDT
+ *
+ * Add public key information to the FDT node, suitable for
+ * verification at run-time. The information added depends on the
+ * algorithm being used.
+ *
+ * @info:	Specifies key and FIT information
+ * @keydest:	Destination FDT blob for public key data
+ * @return: 0, on success, -ve on error
+*/
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest);
+#else
+static inline int rsa_sign(struct image_sign_info *info,
+		const struct image_region region[], int region_count,
+		uint8_t **sigp, uint *sig_len)
+{
+	return -ENXIO;
+}
+
+static inline int rsa_add_verify_data(struct image_sign_info *info,
+				      void *keydest)
+{
+	return -ENXIO;
+}
+#endif
+
+#if IMAGE_ENABLE_VERIFY
+/**
+ * rsa_verify() - Verify a signature against some data
+ *
+ * Verify a RSA PKCS1.5 signature against an expected hash.
+ *
+ * @info:	Specifies key and FIT information
+ * @data:	Pointer to the input data
+ * @data_len:	Data length
+ * @sig:	Signature
+ * @sig_len:	Number of bytes in signature
+ * @return 0 if verified, -ve on error
+ */
+int rsa_verify(struct image_sign_info *info,
+	       const struct image_region region[], int region_count,
+	       uint8_t *sig, uint sig_len);
+#else
+static inline int rsa_verify(struct image_sign_info *info,
+		const struct image_region region[], int region_count,
+		uint8_t *sig, uint sig_len)
+{
+	return -ENXIO;
+}
+#endif
+
+#endif
diff --git a/include/spi.h b/include/spi.h
index 1638b50..e8e6544 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -247,4 +247,20 @@
 	return ret < 0 ? ret : din[1];
 }
 
+/**
+ * Set up a SPI slave for a particular device tree node
+ *
+ * This calls spi_setup_slave() with the correct bus number. Call
+ * spi_free_slave() to free it later.
+ *
+ * @param blob		Device tree blob
+ * @param node		SPI peripheral node to use
+ * @param cs		Chip select to use
+ * @param max_hz	Maximum SCK rate in Hz (0 for default)
+ * @param mode		Clock polarity, clock phase and other parameters
+ * @return pointer to new spi_slave structure
+ */
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
+		unsigned int cs, unsigned int max_hz, unsigned int mode);
+
 #endif	/* _SPI_H_ */
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 3b6a44e..e80785f 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -38,6 +38,16 @@
 	u32		page_size;
 	/* Erase (sector) size */
 	u32		sector_size;
+#ifdef CONFIG_SPI_FLASH_BAR
+	/* Bank read cmd */
+	u8		bank_read_cmd;
+	/* Bank write cmd */
+	u8		bank_write_cmd;
+	/* Current flash bank */
+	u8		bank_curr;
+#endif
+	/* Poll cmd - for flash erase/program */
+	u8		poll_cmd;
 
 	void *memory_map;	/* Address of read-only SPI flash access */
 	int		(*read)(struct spi_flash *flash, u32 offset,
diff --git a/include/trace.h b/include/trace.h
new file mode 100644
index 0000000..8082466
--- /dev/null
+++ b/include/trace.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * 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
+ */
+
+#ifndef __TRACE_H
+#define __TRACE_H
+
+enum {
+	/*
+	 * This affects the granularity of our trace. We can bin function
+	 * entry points into groups on the basis that functions typically
+	 * have a minimum size, so entry points can't appear any closer
+	 * than this to each other.
+	 *
+	 * The value here assumes a minimum instruction size of 4 bytes,
+	 * or that instructions are 2 bytes but there are at least 2 of
+	 * them in every function.
+	 *
+	 * Increasing this value reduces the number of functions we can
+	 * resolve, but reduces the size of the uintptr_t array used for
+	 * our function list, which is the length of the code divided by
+	 * this value.
+	 */
+	FUNC_SITE_SIZE	= 4,	/* distance between function sites */
+};
+
+enum trace_chunk_type {
+	TRACE_CHUNK_FUNCS,
+	TRACE_CHUNK_CALLS,
+};
+
+/* A trace record for a function, as written to the profile output file */
+struct trace_output_func {
+	uint32_t offset;		/* Function offset into code */
+	uint32_t call_count;		/* Number of times called */
+};
+
+/* A header at the start of the trace output buffer */
+struct trace_output_hdr {
+	enum trace_chunk_type type;	/* Record type */
+	uint32_t rec_count;		/* Number of records */
+};
+
+/* Print statistics about traced function calls */
+void trace_print_stats(void);
+
+/**
+ * Dump a list of functions and call counts into a buffer
+ *
+ * Each record in the buffer is a struct trace_func_stats. The 'needed'
+ * parameter returns the number of bytes needed to complete the operation,
+ * which may be more than buff_size if your buffer is too small.
+ *
+ * @param buff		Buffer in which to place data, or NULL to count size
+ * @param buff_size	Size of buffer
+ * @param needed	Returns number of bytes used / needed
+ * @return 0 if ok, -1 on error (buffer exhausted)
+ */
+int trace_list_functions(void *buff, int buff_size, unsigned *needed);
+
+/* Flags for ftrace_record */
+enum ftrace_flags {
+	FUNCF_EXIT		= 0UL << 30,
+	FUNCF_ENTRY		= 1UL << 30,
+	FUNCF_TEXTBASE		= 2UL << 30,
+
+	FUNCF_TIMESTAMP_MASK	= 0x3fffffff,
+};
+
+#define TRACE_CALL_TYPE(call)	((call)->flags & 0xc0000000UL)
+
+/* Information about a single function entry/exit */
+struct trace_call {
+	uint32_t func;		/* Function offset */
+	uint32_t caller;	/* Caller function offset */
+	uint32_t flags;		/* Flags and timestamp */
+};
+
+int trace_list_calls(void *buff, int buff_size, unsigned int *needed);
+
+/**
+ * Turn function tracing on and off
+ *
+ * Don't enable trace if it has not been initialised.
+ *
+ * @param enabled	1 to enable trace, 0 to disable
+ */
+void trace_set_enabled(int enabled);
+
+#ifdef CONFIG_TRACE_EARLY
+int trace_early_init(void);
+#else
+static inline int trace_early_init(void)
+{
+	return 0;
+}
+#endif
+
+/**
+ * Init the trace system
+ *
+ * This should be called after relocation with a suitably large buffer
+ * (typically as large as the U-Boot text area)
+ *
+ * @param buff		Pointer to trace buffer
+ * @param buff_size	Size of trace buffer
+ */
+int trace_init(void *buff, size_t buff_size);
+
+#endif
diff --git a/include/vsprintf.h b/include/vsprintf.h
index 651077c..6568854 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -178,4 +178,15 @@
 #define vscnprintf(buf, size, fmt, args...) vsprintf(buf, fmt, ##args)
 #endif /* CONFIG_SYS_VSNPRINTF */
 
+/**
+ * print_grouped_ull() - print a value with digits grouped by ','
+ *
+ * This prints a value with grouped digits, like 12,345,678 to make it easier
+ * to read.
+ *
+ * @val:	Value to print
+ * @digits:	Number of digiits to print
+ */
+void print_grouped_ull(unsigned long long int_val, int digits);
+
 #endif
diff --git a/lib/Makefile b/lib/Makefile
index 5d58609..f5a8819 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -26,7 +26,6 @@
 LIB	= $(obj)libgeneric.o
 
 ifndef CONFIG_SPL_BUILD
-COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
 COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
@@ -36,13 +35,10 @@
 COBJS-$(CONFIG_USB_TTY) += circbuf.o
 COBJS-y += crc7.o
 COBJS-y += crc16.o
-COBJS-y += display_options.o
-COBJS-y += errno.o
 COBJS-$(CONFIG_OF_CONTROL) += fdtdec.o
 COBJS-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
 COBJS-$(CONFIG_GZIP) += gunzip.o
 COBJS-$(CONFIG_GZIP_COMPRESSED) += gzip.o
-COBJS-y += hashtable.o
 COBJS-y += initcall.o
 COBJS-$(CONFIG_LMB) += lmb.o
 COBJS-y += ldiv.o
@@ -60,14 +56,12 @@
 
 ifdef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += crc32.o
-ifneq ($(CONFIG_SPL_SPI_FLASH_SUPPORT)$(CONFIG_SPL_NET_SUPPORT),)
-COBJS-y += display_options.o
-endif
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += errno.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += hashtable.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
+COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
+COBJS-y += hashtable.o
+COBJS-y += errno.o
+COBJS-y += display_options.o
 COBJS-$(CONFIG_BCH) += bch.o
 COBJS-y += crc32.o
 COBJS-y += ctype.o
@@ -77,6 +71,7 @@
 COBJS-$(CONFIG_REGEX) += slre.o
 COBJS-y += string.o
 COBJS-y += time.o
+COBJS-$(CONFIG_TRACE) += trace.o
 COBJS-$(CONFIG_BOOTP_PXE) += uuid.o
 COBJS-y += vsprintf.o
 COBJS-$(CONFIG_RANDOM_MACADDR) += rand.o
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 005ad3d..b314268 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -57,11 +57,14 @@
 	COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"),
 	COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"),
 	COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"),
+	COMPAT(GOOGLE_CROS_EC, "google,cros-ec"),
+	COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"),
 	COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
 	COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
 	COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
 	COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"),
 	COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
+	COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
 	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
 	COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
 	COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 63e67b7..b9e3c4a 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -120,3 +120,132 @@
 			endoffset - nodeoffset);
 	return 0;
 }
+
+#define FDT_MAX_DEPTH	32
+
+static int str_in_list(const char *str, char * const list[], int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++)
+		if (!strcmp(list[i], str))
+			return 1;
+
+	return 0;
+}
+
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+		     char * const exc_prop[], int exc_prop_count,
+		     struct fdt_region region[], int max_regions,
+		     char *path, int path_len, int add_string_tab)
+{
+	int stack[FDT_MAX_DEPTH];
+	char *end;
+	int nextoffset = 0;
+	uint32_t tag;
+	int count = 0;
+	int start = -1;
+	int depth = -1;
+	int want = 0;
+	int base = fdt_off_dt_struct(fdt);
+
+	end = path;
+	*end = '\0';
+	do {
+		const struct fdt_property *prop;
+		const char *name;
+		const char *str;
+		int include = 0;
+		int stop_at = 0;
+		int offset;
+		int len;
+
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		stop_at = nextoffset;
+
+		switch (tag) {
+		case FDT_PROP:
+			include = want >= 2;
+			stop_at = offset;
+			prop = fdt_get_property_by_offset(fdt, offset, NULL);
+			str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+			if (str_in_list(str, exc_prop, exc_prop_count))
+				include = 0;
+			break;
+
+		case FDT_NOP:
+			include = want >= 2;
+			stop_at = offset;
+			break;
+
+		case FDT_BEGIN_NODE:
+			depth++;
+			if (depth == FDT_MAX_DEPTH)
+				return -FDT_ERR_BADSTRUCTURE;
+			name = fdt_get_name(fdt, offset, &len);
+			if (end - path + 2 + len >= path_len)
+				return -FDT_ERR_NOSPACE;
+			if (end != path + 1)
+				*end++ = '/';
+			strcpy(end, name);
+			end += len;
+			stack[depth] = want;
+			if (want == 1)
+				stop_at = offset;
+			if (str_in_list(path, inc, inc_count))
+				want = 2;
+			else if (want)
+				want--;
+			else
+				stop_at = offset;
+			include = want;
+			break;
+
+		case FDT_END_NODE:
+			include = want;
+			want = stack[depth--];
+			while (end > path && *--end != '/')
+				;
+			*end = '\0';
+			break;
+
+		case FDT_END:
+			include = 1;
+			break;
+		}
+
+		if (include && start == -1) {
+			/* Should we merge with previous? */
+			if (count && count <= max_regions &&
+			    offset == region[count - 1].offset +
+					region[count - 1].size - base)
+				start = region[--count].offset - base;
+			else
+				start = offset;
+		}
+
+		if (!include && start != -1) {
+			if (count < max_regions) {
+				region[count].offset = base + start;
+				region[count].size = stop_at - start;
+			}
+			count++;
+			start = -1;
+		}
+	} while (tag != FDT_END);
+
+	if (nextoffset != fdt_size_dt_struct(fdt))
+		return -FDT_ERR_BADLAYOUT;
+
+	/* Add a region for the END tag and the string table */
+	if (count < max_regions) {
+		region[count].offset = base + start;
+		region[count].size = nextoffset - start;
+		if (add_string_tab)
+			region[count].size += fdt_size_dt_strings(fdt);
+	}
+	count++;
+
+	return count;
+}
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
new file mode 100644
index 0000000..9eb3e40
--- /dev/null
+++ b/lib/rsa/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2013, Google Inc.
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= $(obj)librsa.o
+
+ifdef CONFIG_FIT_SIGNATURE
+COBJS-$(CONFIG_RSA) += rsa-verify.o
+endif
+
+COBJS	:= $(sort $(COBJS-y))
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
new file mode 100644
index 0000000..a75ae24
--- /dev/null
+++ b/lib/rsa/rsa-sign.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2013, Google 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 "mkimage.h"
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <image.h>
+#include <time.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#define HAVE_ERR_REMOVE_THREAD_STATE
+#endif
+
+static int rsa_err(const char *msg)
+{
+	unsigned long sslErr = ERR_get_error();
+
+	fprintf(stderr, "%s", msg);
+	fprintf(stderr, ": %s\n",
+		ERR_error_string(sslErr, 0));
+
+	return -1;
+}
+
+/**
+ * rsa_get_pub_key() - read a public key from a .crt file
+ *
+ * @keydir:	Directory containins the key
+ * @name	Name of key file (will have a .crt extension)
+ * @rsap	Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
+{
+	char path[1024];
+	EVP_PKEY *key;
+	X509 *cert;
+	RSA *rsa;
+	FILE *f;
+	int ret;
+
+	*rsap = NULL;
+	snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
+	f = fopen(path, "r");
+	if (!f) {
+		fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
+			path, strerror(errno));
+		return -EACCES;
+	}
+
+	/* Read the certificate */
+	cert = NULL;
+	if (!PEM_read_X509(f, &cert, NULL, NULL)) {
+		rsa_err("Couldn't read certificate");
+		ret = -EINVAL;
+		goto err_cert;
+	}
+
+	/* Get the public key from the certificate. */
+	key = X509_get_pubkey(cert);
+	if (!key) {
+		rsa_err("Couldn't read public key\n");
+		ret = -EINVAL;
+		goto err_pubkey;
+	}
+
+	/* Convert to a RSA_style key. */
+	rsa = EVP_PKEY_get1_RSA(key);
+	if (!rsa) {
+		rsa_err("Couldn't convert to a RSA style key");
+		goto err_rsa;
+	}
+	fclose(f);
+	EVP_PKEY_free(key);
+	X509_free(cert);
+	*rsap = rsa;
+
+	return 0;
+
+err_rsa:
+	EVP_PKEY_free(key);
+err_pubkey:
+	X509_free(cert);
+err_cert:
+	fclose(f);
+	return ret;
+}
+
+/**
+ * rsa_get_priv_key() - read a private key from a .key file
+ *
+ * @keydir:	Directory containins the key
+ * @name	Name of key file (will have a .key extension)
+ * @rsap	Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
+{
+	char path[1024];
+	RSA *rsa;
+	FILE *f;
+
+	*rsap = NULL;
+	snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
+	f = fopen(path, "r");
+	if (!f) {
+		fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
+			path, strerror(errno));
+		return -ENOENT;
+	}
+
+	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
+	if (!rsa) {
+		rsa_err("Failure reading private key");
+		fclose(f);
+		return -EPROTO;
+	}
+	fclose(f);
+	*rsap = rsa;
+
+	return 0;
+}
+
+static int rsa_init(void)
+{
+	int ret;
+
+	ret = SSL_library_init();
+	if (!ret) {
+		fprintf(stderr, "Failure to init SSL library\n");
+		return -1;
+	}
+	SSL_load_error_strings();
+
+	OpenSSL_add_all_algorithms();
+	OpenSSL_add_all_digests();
+	OpenSSL_add_all_ciphers();
+
+	return 0;
+}
+
+static void rsa_remove(void)
+{
+	CRYPTO_cleanup_all_ex_data();
+	ERR_free_strings();
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
+	ERR_remove_thread_state(NULL);
+#else
+	ERR_remove_state(0);
+#endif
+	EVP_cleanup();
+}
+
+static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
+		int region_count, uint8_t **sigp, uint *sig_size)
+{
+	EVP_PKEY *key;
+	EVP_MD_CTX *context;
+	int size, ret = 0;
+	uint8_t *sig;
+	int i;
+
+	key = EVP_PKEY_new();
+	if (!key)
+		return rsa_err("EVP_PKEY object creation failed");
+
+	if (!EVP_PKEY_set1_RSA(key, rsa)) {
+		ret = rsa_err("EVP key setup failed");
+		goto err_set;
+	}
+
+	size = EVP_PKEY_size(key);
+	sig = malloc(size);
+	if (!sig) {
+		fprintf(stderr, "Out of memory for signature (%d bytes)\n",
+			size);
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	context = EVP_MD_CTX_create();
+	if (!context) {
+		ret = rsa_err("EVP context creation failed");
+		goto err_create;
+	}
+	EVP_MD_CTX_init(context);
+	if (!EVP_SignInit(context, EVP_sha1())) {
+		ret = rsa_err("Signer setup failed");
+		goto err_sign;
+	}
+
+	for (i = 0; i < region_count; i++) {
+		if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
+			ret = rsa_err("Signing data failed");
+			goto err_sign;
+		}
+	}
+
+	if (!EVP_SignFinal(context, sig, sig_size, key)) {
+		ret = rsa_err("Could not obtain signature");
+		goto err_sign;
+	}
+	EVP_MD_CTX_cleanup(context);
+	EVP_MD_CTX_destroy(context);
+	EVP_PKEY_free(key);
+
+	debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
+	*sigp = sig;
+	*sig_size = size;
+
+	return 0;
+
+err_sign:
+	EVP_MD_CTX_destroy(context);
+err_create:
+	free(sig);
+err_alloc:
+err_set:
+	EVP_PKEY_free(key);
+	return ret;
+}
+
+int rsa_sign(struct image_sign_info *info,
+	     const struct image_region region[], int region_count,
+	     uint8_t **sigp, uint *sig_len)
+{
+	RSA *rsa;
+	int ret;
+
+	ret = rsa_init();
+	if (ret)
+		return ret;
+
+	ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
+	if (ret)
+		goto err_priv;
+	ret = rsa_sign_with_key(rsa, region, region_count, sigp, sig_len);
+	if (ret)
+		goto err_sign;
+
+	RSA_free(rsa);
+	rsa_remove();
+
+	return ret;
+
+err_sign:
+	RSA_free(rsa);
+err_priv:
+	rsa_remove();
+	return ret;
+}
+
+/*
+ * rsa_get_params(): - Get the important parameters of an RSA public key
+ */
+int rsa_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
+		   BIGNUM **r_squaredp)
+{
+	BIGNUM *big1, *big2, *big32, *big2_32;
+	BIGNUM *n, *r, *r_squared, *tmp;
+	BN_CTX *bn_ctx = BN_CTX_new();
+	int ret = 0;
+
+	/* Initialize BIGNUMs */
+	big1 = BN_new();
+	big2 = BN_new();
+	big32 = BN_new();
+	r = BN_new();
+	r_squared = BN_new();
+	tmp = BN_new();
+	big2_32 = BN_new();
+	n = BN_new();
+	if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
+	    !n) {
+		fprintf(stderr, "Out of memory (bignum)\n");
+		return -ENOMEM;
+	}
+
+	if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
+	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
+		ret = -1;
+
+	/* big2_32 = 2^32 */
+	if (!BN_exp(big2_32, big2, big32, bn_ctx))
+		ret = -1;
+
+	/* Calculate n0_inv = -1 / n[0] mod 2^32 */
+	if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
+	    !BN_sub(tmp, big2_32, tmp))
+		ret = -1;
+	*n0_invp = BN_get_word(tmp);
+
+	/* Calculate R = 2^(# of key bits) */
+	if (!BN_set_word(tmp, BN_num_bits(n)) ||
+	    !BN_exp(r, big2, tmp, bn_ctx))
+		ret = -1;
+
+	/* Calculate r_squared = R^2 mod n */
+	if (!BN_copy(r_squared, r) ||
+	    !BN_mul(tmp, r_squared, r, bn_ctx) ||
+	    !BN_mod(r_squared, tmp, n, bn_ctx))
+		ret = -1;
+
+	*modulusp = n;
+	*r_squaredp = r_squared;
+
+	BN_free(big1);
+	BN_free(big2);
+	BN_free(big32);
+	BN_free(r);
+	BN_free(tmp);
+	BN_free(big2_32);
+	if (ret) {
+		fprintf(stderr, "Bignum operations failed\n");
+		return -ENOMEM;
+	}
+
+	return ret;
+}
+
+static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
+			  BIGNUM *num, int num_bits)
+{
+	int nwords = num_bits / 32;
+	int size;
+	uint32_t *buf, *ptr;
+	BIGNUM *tmp, *big2, *big32, *big2_32;
+	BN_CTX *ctx;
+	int ret;
+
+	tmp = BN_new();
+	big2 = BN_new();
+	big32 = BN_new();
+	big2_32 = BN_new();
+	if (!tmp || !big2 || !big32 || !big2_32) {
+		fprintf(stderr, "Out of memory (bignum)\n");
+		return -ENOMEM;
+	}
+	ctx = BN_CTX_new();
+	if (!tmp) {
+		fprintf(stderr, "Out of memory (bignum context)\n");
+		return -ENOMEM;
+	}
+	BN_set_word(big2, 2L);
+	BN_set_word(big32, 32L);
+	BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
+
+	size = nwords * sizeof(uint32_t);
+	buf = malloc(size);
+	if (!buf) {
+		fprintf(stderr, "Out of memory (%d bytes)\n", size);
+		return -ENOMEM;
+	}
+
+	/* Write out modulus as big endian array of integers */
+	for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
+		BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
+		*ptr = cpu_to_fdt32(BN_get_word(tmp));
+		BN_rshift(num, num, 32); /*  N = N/B */
+	}
+
+	ret = fdt_setprop(blob, noffset, prop_name, buf, size);
+	if (ret) {
+		fprintf(stderr, "Failed to write public key to FIT\n");
+		return -ENOSPC;
+	}
+	free(buf);
+	BN_free(tmp);
+	BN_free(big2);
+	BN_free(big32);
+	BN_free(big2_32);
+
+	return ret;
+}
+
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+{
+	BIGNUM *modulus, *r_squared;
+	uint32_t n0_inv;
+	int parent, node;
+	char name[100];
+	int ret;
+	int bits;
+	RSA *rsa;
+
+	debug("%s: Getting verification data\n", __func__);
+	ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
+	if (ret)
+		return ret;
+	ret = rsa_get_params(rsa, &n0_inv, &modulus, &r_squared);
+	if (ret)
+		return ret;
+	bits = BN_num_bits(modulus);
+	parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
+	if (parent == -FDT_ERR_NOTFOUND) {
+		parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
+		if (parent < 0) {
+			fprintf(stderr, "Couldn't create signature node: %s\n",
+				fdt_strerror(parent));
+			return -EINVAL;
+		}
+	}
+
+	/* Either create or overwrite the named key node */
+	snprintf(name, sizeof(name), "key-%s", info->keyname);
+	node = fdt_subnode_offset(keydest, parent, name);
+	if (node == -FDT_ERR_NOTFOUND) {
+		node = fdt_add_subnode(keydest, parent, name);
+		if (node < 0) {
+			fprintf(stderr, "Could not create key subnode: %s\n",
+				fdt_strerror(node));
+			return -EINVAL;
+		}
+	} else if (node < 0) {
+		fprintf(stderr, "Cannot select keys parent: %s\n",
+			fdt_strerror(node));
+		return -ENOSPC;
+	}
+
+	ret = fdt_setprop_string(keydest, node, "key-name-hint",
+				 info->keyname);
+	ret |= fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
+	ret |= fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
+	ret |= fdt_add_bignum(keydest, node, "rsa,modulus", modulus, bits);
+	ret |= fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared, bits);
+	ret |= fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
+				  info->algo->name);
+	if (info->require_keys) {
+		fdt_setprop_string(keydest, node, "required",
+				   info->require_keys);
+	}
+	BN_free(modulus);
+	BN_free(r_squared);
+	if (ret)
+		return -EIO;
+
+	return 0;
+}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
new file mode 100644
index 0000000..6a02689
--- /dev/null
+++ b/lib/rsa/rsa-verify.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2013, Google 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 <fdtdec.h>
+#include <rsa.h>
+#include <sha1.h>
+#include <asm/byteorder.h>
+#include <asm/errno.h>
+#include <asm/unaligned.h>
+
+/**
+ * struct rsa_public_key - holder for a public key
+ *
+ * An RSA public key consists of a modulus (typically called N), the inverse
+ * and R^2, where R is 2^(# key bits).
+ */
+struct rsa_public_key {
+	uint len;		/* Length of modulus[] in number of uint32_t */
+	uint32_t n0inv;		/* -1 / modulus[0] mod 2^32 */
+	uint32_t *modulus;	/* modulus as little endian array */
+	uint32_t *rr;		/* R^2 as little endian array */
+};
+
+#define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
+
+#define RSA2048_BYTES	(2048 / 8)
+
+/* This is the minimum/maximum key size we support, in bits */
+#define RSA_MIN_KEY_BITS	2048
+#define RSA_MAX_KEY_BITS	2048
+
+/* This is the maximum signature length that we support, in bits */
+#define RSA_MAX_SIG_BITS	2048
+
+static const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
+	0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
+	0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+	0x05, 0x00, 0x04, 0x14
+};
+
+/**
+ * subtract_modulus() - subtract modulus from the given value
+ *
+ * @key:	Key containing modulus to subtract
+ * @num:	Number to subtract modulus from, as little endian word array
+ */
+static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
+{
+	int64_t acc = 0;
+	uint i;
+
+	for (i = 0; i < key->len; i++) {
+		acc += (uint64_t)num[i] - key->modulus[i];
+		num[i] = (uint32_t)acc;
+		acc >>= 32;
+	}
+}
+
+/**
+ * greater_equal_modulus() - check if a value is >= modulus
+ *
+ * @key:	Key containing modulus to check
+ * @num:	Number to check against modulus, as little endian word array
+ * @return 0 if num < modulus, 1 if num >= modulus
+ */
+static int greater_equal_modulus(const struct rsa_public_key *key,
+				 uint32_t num[])
+{
+	uint32_t i;
+
+	for (i = key->len - 1; i >= 0; i--) {
+		if (num[i] < key->modulus[i])
+			return 0;
+		if (num[i] > key->modulus[i])
+			return 1;
+	}
+
+	return 1;  /* equal */
+}
+
+/**
+ * montgomery_mul_add_step() - Perform montgomery multiply-add step
+ *
+ * Operation: montgomery result[] += a * b[] / n0inv % modulus
+ *
+ * @key:	RSA key
+ * @result:	Place to put result, as little endian word array
+ * @a:		Multiplier
+ * @b:		Multiplicand, as little endian word array
+ */
+static void montgomery_mul_add_step(const struct rsa_public_key *key,
+		uint32_t result[], const uint32_t a, const uint32_t b[])
+{
+	uint64_t acc_a, acc_b;
+	uint32_t d0;
+	uint i;
+
+	acc_a = (uint64_t)a * b[0] + result[0];
+	d0 = (uint32_t)acc_a * key->n0inv;
+	acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
+	for (i = 1; i < key->len; i++) {
+		acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
+		acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
+				(uint32_t)acc_a;
+		result[i - 1] = (uint32_t)acc_b;
+	}
+
+	acc_a = (acc_a >> 32) + (acc_b >> 32);
+
+	result[i - 1] = (uint32_t)acc_a;
+
+	if (acc_a >> 32)
+		subtract_modulus(key, result);
+}
+
+/**
+ * montgomery_mul() - Perform montgomery mutitply
+ *
+ * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
+ *
+ * @key:	RSA key
+ * @result:	Place to put result, as little endian word array
+ * @a:		Multiplier, as little endian word array
+ * @b:		Multiplicand, as little endian word array
+ */
+static void montgomery_mul(const struct rsa_public_key *key,
+		uint32_t result[], uint32_t a[], const uint32_t b[])
+{
+	uint i;
+
+	for (i = 0; i < key->len; ++i)
+		result[i] = 0;
+	for (i = 0; i < key->len; ++i)
+		montgomery_mul_add_step(key, result, a[i], b);
+}
+
+/**
+ * pow_mod() - in-place public exponentiation
+ *
+ * @key:	RSA key
+ * @inout:	Big-endian word array containing value and result
+ */
+static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
+{
+	uint32_t *result, *ptr;
+	uint i;
+
+	/* Sanity check for stack size - key->len is in 32-bit words */
+	if (key->len > RSA_MAX_KEY_BITS / 32) {
+		debug("RSA key words %u exceeds maximum %d\n", key->len,
+		      RSA_MAX_KEY_BITS / 32);
+		return -EINVAL;
+	}
+
+	uint32_t val[key->len], acc[key->len], tmp[key->len];
+	result = tmp;  /* Re-use location. */
+
+	/* Convert from big endian byte array to little endian word array. */
+	for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
+		val[i] = get_unaligned_be32(ptr);
+
+	montgomery_mul(key, acc, val, key->rr);  /* axx = a * RR / R mod M */
+	for (i = 0; i < 16; i += 2) {
+		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
+		montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
+	}
+	montgomery_mul(key, result, acc, val);  /* result = XX * a / R mod M */
+
+	/* Make sure result < mod; result is at most 1x mod too large. */
+	if (greater_equal_modulus(key, result))
+		subtract_modulus(key, result);
+
+	/* Convert to bigendian byte array */
+	for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
+		put_unaligned_be32(result[i], ptr);
+
+	return 0;
+}
+
+static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
+		const uint32_t sig_len, const uint8_t *hash)
+{
+	const uint8_t *padding;
+	int pad_len;
+	int ret;
+
+	if (!key || !sig || !hash)
+		return -EIO;
+
+	if (sig_len != (key->len * sizeof(uint32_t))) {
+		debug("Signature is of incorrect length %d\n", sig_len);
+		return -EINVAL;
+	}
+
+	/* Sanity check for stack size */
+	if (sig_len > RSA_MAX_SIG_BITS / 8) {
+		debug("Signature length %u exceeds maximum %d\n", sig_len,
+		      RSA_MAX_SIG_BITS / 8);
+		return -EINVAL;
+	}
+
+	uint32_t buf[sig_len / sizeof(uint32_t)];
+
+	memcpy(buf, sig, sig_len);
+
+	ret = pow_mod(key, buf);
+	if (ret)
+		return ret;
+
+	/* Determine padding to use depending on the signature type. */
+	padding = padding_sha1_rsa2048;
+	pad_len = RSA2048_BYTES - SHA1_SUM_LEN;
+
+	/* Check pkcs1.5 padding bytes. */
+	if (memcmp(buf, padding, pad_len)) {
+		debug("In RSAVerify(): Padding check failed!\n");
+		return -EINVAL;
+	}
+
+	/* Check hash. */
+	if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
+		debug("In RSAVerify(): Hash check failed!\n");
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		dst[i] = fdt32_to_cpu(src[len - 1 - i]);
+}
+
+static int rsa_verify_with_keynode(struct image_sign_info *info,
+		const void *hash, uint8_t *sig, uint sig_len, int node)
+{
+	const void *blob = info->fdt_blob;
+	struct rsa_public_key key;
+	const void *modulus, *rr;
+	int ret;
+
+	if (node < 0) {
+		debug("%s: Skipping invalid node", __func__);
+		return -EBADF;
+	}
+	if (!fdt_getprop(blob, node, "rsa,n0-inverse", NULL)) {
+		debug("%s: Missing rsa,n0-inverse", __func__);
+		return -EFAULT;
+	}
+	key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
+	key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
+	modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
+	rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
+	if (!key.len || !modulus || !rr) {
+		debug("%s: Missing RSA key info", __func__);
+		return -EFAULT;
+	}
+
+	/* Sanity check for stack size */
+	if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
+		debug("RSA key bits %u outside allowed range %d..%d\n",
+		      key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
+		return -EFAULT;
+	}
+	key.len /= sizeof(uint32_t) * 8;
+	uint32_t key1[key.len], key2[key.len];
+
+	key.modulus = key1;
+	key.rr = key2;
+	rsa_convert_big_endian(key.modulus, modulus, key.len);
+	rsa_convert_big_endian(key.rr, rr, key.len);
+	if (!key.modulus || !key.rr) {
+		debug("%s: Out of memory", __func__);
+		return -ENOMEM;
+	}
+
+	debug("key length %d\n", key.len);
+	ret = rsa_verify_key(&key, sig, sig_len, hash);
+	if (ret) {
+		printf("%s: RSA failed to verify: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int rsa_verify(struct image_sign_info *info,
+	       const struct image_region region[], int region_count,
+	       uint8_t *sig, uint sig_len)
+{
+	const void *blob = info->fdt_blob;
+	uint8_t hash[SHA1_SUM_LEN];
+	int ndepth, noffset;
+	int sig_node, node;
+	char name[100];
+	sha1_context ctx;
+	int ret, i;
+
+	sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found\n", __func__);
+		return -ENOENT;
+	}
+
+	sha1_starts(&ctx);
+	for (i = 0; i < region_count; i++)
+		sha1_update(&ctx, region[i].data, region[i].size);
+	sha1_finish(&ctx, hash);
+
+	/* See if we must use a particular key */
+	if (info->required_keynode != -1) {
+		ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+			info->required_keynode);
+		if (!ret)
+			return ret;
+	}
+
+	/* Look for a key that matches our hint */
+	snprintf(name, sizeof(name), "key-%s", info->keyname);
+	node = fdt_subnode_offset(blob, sig_node, name);
+	ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
+	if (!ret)
+		return ret;
+
+	/* No luck, so try each of the keys in turn */
+	for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
+			(noffset >= 0) && (ndepth > 0);
+			noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
+		if (ndepth == 1 && noffset != node) {
+			ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+						      noffset);
+			if (!ret)
+				break;
+		}
+	}
+
+	return ret;
+}
diff --git a/lib/trace.c b/lib/trace.c
new file mode 100644
index 0000000..e7455bc
--- /dev/null
+++ b/lib/trace.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * 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 <trace.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char trace_enabled __attribute__((section(".data")));
+static char trace_inited __attribute__((section(".data")));
+
+/* The header block at the start of the trace memory area */
+struct trace_hdr {
+	int func_count;		/* Total number of function call sites */
+	u64 call_count;		/* Total number of tracked function calls */
+	u64 untracked_count;	/* Total number of untracked function calls */
+	int funcs_used;		/* Total number of functions used */
+
+	/*
+	 * Call count for each function. This is indexed by the word offset
+	 * of the function from gd->relocaddr
+	 */
+	uintptr_t *call_accum;
+
+	/* Function trace list */
+	struct trace_call *ftrace;	/* The function call records */
+	ulong ftrace_size;	/* Num. of ftrace records we have space for */
+	ulong ftrace_count;	/* Num. of ftrace records written */
+	ulong ftrace_too_deep_count;	/* Functions that were too deep */
+
+	int depth;
+	int depth_limit;
+	int max_depth;
+};
+
+static struct trace_hdr *hdr;	/* Pointer to start of trace buffer */
+
+static inline uintptr_t __attribute__((no_instrument_function))
+		func_ptr_to_num(void *func_ptr)
+{
+	uintptr_t offset = (uintptr_t)func_ptr;
+
+#ifdef CONFIG_SANDBOX
+	offset -= (uintptr_t)&_init;
+#else
+	if (gd->flags & GD_FLG_RELOC)
+		offset -= gd->relocaddr;
+	else
+		offset -= CONFIG_SYS_TEXT_BASE;
+#endif
+	return offset / FUNC_SITE_SIZE;
+}
+
+static void __attribute__((no_instrument_function)) add_ftrace(void *func_ptr,
+				void *caller, ulong flags)
+{
+	if (hdr->depth > hdr->depth_limit) {
+		hdr->ftrace_too_deep_count++;
+		return;
+	}
+	if (hdr->ftrace_count < hdr->ftrace_size) {
+		struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
+
+		rec->func = func_ptr_to_num(func_ptr);
+		rec->caller = func_ptr_to_num(caller);
+		rec->flags = flags | (timer_get_us() & FUNCF_TIMESTAMP_MASK);
+	}
+	hdr->ftrace_count++;
+}
+
+static void __attribute__((no_instrument_function)) add_textbase(void)
+{
+	if (hdr->ftrace_count < hdr->ftrace_size) {
+		struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
+
+		rec->func = CONFIG_SYS_TEXT_BASE;
+		rec->caller = 0;
+		rec->flags = FUNCF_TEXTBASE;
+	}
+	hdr->ftrace_count++;
+}
+
+/**
+ * This is called on every function entry
+ *
+ * We add to our tally for this function and add to the list of called
+ * functions.
+ *
+ * @param func_ptr	Pointer to function being entered
+ * @param caller	Pointer to function which called this function
+ */
+void __attribute__((no_instrument_function)) __cyg_profile_func_enter(
+		void *func_ptr, void *caller)
+{
+	if (trace_enabled) {
+		int func;
+
+		add_ftrace(func_ptr, caller, FUNCF_ENTRY);
+		func = func_ptr_to_num(func_ptr);
+		if (func < hdr->func_count) {
+			hdr->call_accum[func]++;
+			hdr->call_count++;
+		} else {
+			hdr->untracked_count++;
+		}
+		hdr->depth++;
+		if (hdr->depth > hdr->depth_limit)
+			hdr->max_depth = hdr->depth;
+	}
+}
+
+/**
+ * This is called on every function exit
+ *
+ * We do nothing here.
+ *
+ * @param func_ptr	Pointer to function being entered
+ * @param caller	Pointer to function which called this function
+ */
+void __attribute__((no_instrument_function)) __cyg_profile_func_exit(
+		void *func_ptr, void *caller)
+{
+	if (trace_enabled) {
+		add_ftrace(func_ptr, caller, FUNCF_EXIT);
+		hdr->depth--;
+	}
+}
+
+/**
+ * Produce a list of called functions
+ *
+ * The information is written into the supplied buffer - a header followed
+ * by a list of function records.
+ *
+ * @param buff		Buffer to place list into
+ * @param buff_size	Size of buffer
+ * @param needed	Returns size of buffer needed, which may be
+ *			greater than buff_size if we ran out of space.
+ * @return 0 if ok, -1 if space was exhausted
+ */
+int trace_list_functions(void *buff, int buff_size, unsigned int *needed)
+{
+	struct trace_output_hdr *output_hdr = NULL;
+	void *end, *ptr = buff;
+	int func;
+	int upto;
+
+	end = buff ? buff + buff_size : NULL;
+
+	/* Place some header information */
+	if (ptr + sizeof(struct trace_output_hdr) < end)
+		output_hdr = ptr;
+	ptr += sizeof(struct trace_output_hdr);
+
+	/* Add information about each function */
+	for (func = upto = 0; func < hdr->func_count; func++) {
+		int calls = hdr->call_accum[func];
+
+		if (!calls)
+			continue;
+
+		if (ptr + sizeof(struct trace_output_func) < end) {
+			struct trace_output_func *stats = ptr;
+
+			stats->offset = func * FUNC_SITE_SIZE;
+			stats->call_count = calls;
+			upto++;
+		}
+		ptr += sizeof(struct trace_output_func);
+	}
+
+	/* Update the header */
+	if (output_hdr) {
+		output_hdr->rec_count = upto;
+		output_hdr->type = TRACE_CHUNK_FUNCS;
+	}
+
+	/* Work out how must of the buffer we used */
+	*needed = ptr - buff;
+	if (ptr > end)
+		return -1;
+	return 0;
+}
+
+int trace_list_calls(void *buff, int buff_size, unsigned *needed)
+{
+	struct trace_output_hdr *output_hdr = NULL;
+	void *end, *ptr = buff;
+	int rec, upto;
+	int count;
+
+	end = buff ? buff + buff_size : NULL;
+
+	/* Place some header information */
+	if (ptr + sizeof(struct trace_output_hdr) < end)
+		output_hdr = ptr;
+	ptr += sizeof(struct trace_output_hdr);
+
+	/* Add information about each call */
+	count = hdr->ftrace_count;
+	if (count > hdr->ftrace_size)
+		count = hdr->ftrace_size;
+	for (rec = upto = 0; rec < count; rec++) {
+		if (ptr + sizeof(struct trace_call) < end) {
+			struct trace_call *call = &hdr->ftrace[rec];
+			struct trace_call *out = ptr;
+
+			out->func = call->func * FUNC_SITE_SIZE;
+			out->caller = call->caller * FUNC_SITE_SIZE;
+			out->flags = call->flags;
+			upto++;
+		}
+		ptr += sizeof(struct trace_call);
+	}
+
+	/* Update the header */
+	if (output_hdr) {
+		output_hdr->rec_count = upto;
+		output_hdr->type = TRACE_CHUNK_CALLS;
+	}
+
+	/* Work out how must of the buffer we used */
+	*needed = ptr - buff;
+	if (ptr > end)
+		return -1;
+	return 0;
+}
+
+/* Print basic information about tracing */
+void trace_print_stats(void)
+{
+	ulong count;
+
+#ifndef FTRACE
+	puts("Warning: make U-Boot with FTRACE to enable function instrumenting.\n");
+	puts("You will likely get zeroed data here\n");
+#endif
+	if (!trace_inited) {
+		printf("Trace is disabled\n");
+		return;
+	}
+	print_grouped_ull(hdr->func_count, 10);
+	puts(" function sites\n");
+	print_grouped_ull(hdr->call_count, 10);
+	puts(" function calls\n");
+	print_grouped_ull(hdr->untracked_count, 10);
+	puts(" untracked function calls\n");
+	count = min(hdr->ftrace_count, hdr->ftrace_size);
+	print_grouped_ull(count, 10);
+	puts(" traced function calls");
+	if (hdr->ftrace_count > hdr->ftrace_size) {
+		printf(" (%lu dropped due to overflow)",
+		       hdr->ftrace_count - hdr->ftrace_size);
+	}
+	puts("\n");
+	printf("%15d maximum observed call depth\n", hdr->max_depth);
+	printf("%15d call depth limit\n", hdr->depth_limit);
+	print_grouped_ull(hdr->ftrace_too_deep_count, 10);
+	puts(" calls not traced due to depth\n");
+}
+
+void __attribute__((no_instrument_function)) trace_set_enabled(int enabled)
+{
+	trace_enabled = enabled != 0;
+}
+
+/**
+ * Init the tracing system ready for used, and enable it
+ *
+ * @param buff		Pointer to trace buffer
+ * @param buff_size	Size of trace buffer
+ */
+int __attribute__((no_instrument_function)) trace_init(void *buff,
+		size_t buff_size)
+{
+	ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
+	size_t needed;
+	int was_disabled = !trace_enabled;
+
+	if (!was_disabled) {
+#ifdef CONFIG_TRACE_EARLY
+		char *end;
+		ulong used;
+
+		/*
+		 * Copy over the early trace data if we have it. Disable
+		 * tracing while we are doing this.
+		 */
+		trace_enabled = 0;
+		hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR,
+				 CONFIG_TRACE_EARLY_SIZE);
+		end = (char *)&hdr->ftrace[hdr->ftrace_count];
+		used = end - (char *)hdr;
+		printf("trace: copying %08lx bytes of early data from %x to %08lx\n",
+		       used, CONFIG_TRACE_EARLY_ADDR,
+		       (ulong)map_to_sysmem(buff));
+		memcpy(buff, hdr, used);
+#else
+		puts("trace: already enabled\n");
+		return -1;
+#endif
+	}
+	hdr = (struct trace_hdr *)buff;
+	needed = sizeof(*hdr) + func_count * sizeof(uintptr_t);
+	if (needed > buff_size) {
+		printf("trace: buffer size %zd bytes: at least %zd needed\n",
+		       buff_size, needed);
+		return -1;
+	}
+
+	if (was_disabled)
+		memset(hdr, '\0', needed);
+	hdr->func_count = func_count;
+	hdr->call_accum = (uintptr_t *)(hdr + 1);
+
+	/* Use any remaining space for the timed function trace */
+	hdr->ftrace = (struct trace_call *)(buff + needed);
+	hdr->ftrace_size = (buff_size - needed) / sizeof(*hdr->ftrace);
+	add_textbase();
+
+	puts("trace: enabled\n");
+	hdr->depth_limit = 15;
+	trace_enabled = 1;
+	trace_inited = 1;
+	return 0;
+}
+
+#ifdef CONFIG_TRACE_EARLY
+int __attribute__((no_instrument_function)) trace_early_init(void)
+{
+	ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
+	size_t buff_size = CONFIG_TRACE_EARLY_SIZE;
+	size_t needed;
+
+	/* We can ignore additional calls to this function */
+	if (trace_enabled)
+		return 0;
+
+	hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR, CONFIG_TRACE_EARLY_SIZE);
+	needed = sizeof(*hdr) + func_count * sizeof(uintptr_t);
+	if (needed > buff_size) {
+		printf("trace: buffer size is %zd bytes, at least %zd needed\n",
+		       buff_size, needed);
+		return -1;
+	}
+
+	memset(hdr, '\0', needed);
+	hdr->call_accum = (uintptr_t *)(hdr + 1);
+	hdr->func_count = func_count;
+
+	/* Use any remaining space for the timed function trace */
+	hdr->ftrace = (struct trace_call *)((char *)hdr + needed);
+	hdr->ftrace_size = (buff_size - needed) / sizeof(*hdr->ftrace);
+	add_textbase();
+	hdr->depth_limit = 200;
+	printf("trace: early enable at %08x\n", CONFIG_TRACE_EARLY_ADDR);
+
+	trace_enabled = 1;
+	return 0;
+}
+#endif
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 533a96b..82e5c13 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -870,3 +870,19 @@
 	} while (i > 0);
 	return p + 1;
 }
+
+/* We don't seem to have %'d in U-Boot */
+void print_grouped_ull(unsigned long long int_val, int digits)
+{
+	char str[21], *s;
+	int grab = 3;
+
+	digits = (digits + 2) / 3;
+	sprintf(str, "%*llu", digits * 3, int_val);
+	for (s = str; *s; s += grab) {
+		if (s != str)
+			putc(s[-1] != ' ' ? ',' : ' ');
+		printf("%.*s", grab, s);
+		grab = 3;
+	}
+}
diff --git a/nand_spl/board/freescale/p1010rdb/Makefile b/nand_spl/board/freescale/p1010rdb/Makefile
deleted file mode 100644
index f7bdf92..0000000
--- a/nand_spl/board/freescale/p1010rdb/Makefile
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# (C) Copyright 2007
-# Stefan Roese, DENX Software Engineering, sr@denx.de.
-#
-# Copyright 2011 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
-#
-
-NAND_SPL := y
-CONFIG_SYS_TEXT_BASE_SPL := 0xff800000
-PAD_TO := 0xff802000
-
-include $(TOPDIR)/config.mk
-
-nandobj	:= $(OBJTREE)/nand_spl/
-
-LDSCRIPT= $(TOPDIR)/$(CPUDIR)/u-boot-nand_spl.lds
-LDFLAGS := -T $(nandobj)u-boot-nand_spl.lds -Ttext $(CONFIG_SYS_TEXT_BASE_SPL) $(LDFLAGS) \
-	   $(LDFLAGS_FINAL)
-AFLAGS	+= -DCONFIG_NAND_SPL
-CFLAGS	+= -DCONFIG_NAND_SPL
-
-SOBJS	= start.o resetvec.o ticks.o
-COBJS	= cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
-	  nand_boot.o nand_boot_fsl_ifc.o ns16550.o tlb.o tlb_table.o
-
-SRCS	:= $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
-OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
-__OBJS	:= $(SOBJS) $(COBJS)
-LNDIR	:= $(nandobj)board/$(BOARDDIR)
-
-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) $(nandobj)u-boot-nand_spl.lds
-	cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) $(PLATFORM_LIBS) \
-		-Map $(nandobj)u-boot-spl.map \
-		-o $(nandobj)u-boot-spl
-
-$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT)
-	$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)board/$(BOARDDIR) \
-		 -ansi -D__ASSEMBLY__ -P - <$< >$@
-
-# create symbolic links for common files
-
-$(obj)cache.c:
-	@rm -f $(obj)cache.c
-	ln -sf $(SRCTREE)/arch/powerpc/lib/cache.c $(obj)cache.c
-
-$(obj)cpu_init_early.c:
-	@rm -f $(obj)cpu_init_early.c
-	ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_early.c $(obj)cpu_init_early.c
-
-$(obj)spl_minimal.c:
-	@rm -f $(obj)spl_minimal.c
-	ln -sf $(SRCTREE)/$(CPUDIR)/spl_minimal.c $(obj)spl_minimal.c
-
-$(obj)fsl_law.c:
-	@rm -f $(obj)fsl_law.c
-	ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
-
-$(obj)law.c:
-	@rm -f $(obj)law.c
-	ln -sf $(SRCTREE)/board/$(BOARDDIR)/law.c $(obj)law.c
-
-$(obj)nand_boot_fsl_ifc.c:
-	@rm -f $(obj)nand_boot_fsl_ifc.c
-	ln -sf $(SRCTREE)/nand_spl/nand_boot_fsl_ifc.c \
-	       $(obj)nand_boot_fsl_ifc.c
-
-$(obj)ns16550.c:
-	@rm -f $(obj)ns16550.c
-	ln -sf $(SRCTREE)/drivers/serial/ns16550.c $(obj)ns16550.c
-
-$(obj)resetvec.S:
-	@rm -f $(obj)resetvec.S
-	ln -s $(SRCTREE)/$(CPUDIR)/resetvec.S $(obj)resetvec.S
-
-$(obj)fixed_ivor.S:
-	@rm -f $(obj)fixed_ivor.S
-	ln -sf $(SRCTREE)/$(CPUDIR)/fixed_ivor.S $(obj)fixed_ivor.S
-
-$(obj)start.S: $(obj)fixed_ivor.S
-	@rm -f $(obj)start.S
-	ln -sf $(SRCTREE)/$(CPUDIR)/start.S $(obj)start.S
-
-$(obj)ticks.S:
-	@rm -f $(obj)ticks.S
-	ln -sf $(SRCTREE)/arch/powerpc/lib/ticks.S $(obj)ticks.S
-
-$(obj)tlb.c:
-	@rm -f $(obj)tlb.c
-	ln -sf $(SRCTREE)/$(CPUDIR)/tlb.c $(obj)tlb.c
-
-$(obj)tlb_table.c:
-	@rm -f $(obj)tlb_table.c
-	ln -sf $(SRCTREE)/board/$(BOARDDIR)/tlb.c $(obj)tlb_table.c
-
-ifneq ($(OBJTREE), $(SRCTREE))
-$(obj)nand_boot.c:
-	@rm -f $(obj)nand_boot.c
-	ln -s $(SRCTREE)/nand_spl/board/$(BOARDDIR)/nand_boot.c $(obj)nand_boot.c
-endif
-
-#########################################################################
-
-$(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/net/link_local.c b/net/link_local.c
index 1ba796e..4152fae 100644
--- a/net/link_local.c
+++ b/net/link_local.c
@@ -206,6 +206,7 @@
 {
 	int source_ip_conflict;
 	int target_ip_conflict;
+	IPaddr_t null_ip = 0;
 
 	if (state == DISABLED)
 		return;
@@ -267,10 +268,18 @@
 	) {
 		source_ip_conflict = 1;
 	}
-	if (arp->ar_op == htons(ARPOP_REQUEST)
-	 && memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0
-	 && memcmp(&arp->ar_tha, NetOurEther, ARP_HLEN) != 0
-	) {
+
+	/*
+	 * According to RFC 3927, section 2.2.1:
+	 * Check if packet is an ARP probe by checking for a null source IP
+	 * then check that target IP is equal to ours and source hw addr
+	 * is not equal to ours. This condition should cause a conflict only
+	 * during probe.
+	 */
+	if (arp->ar_op == htons(ARPOP_REQUEST) &&
+	    memcmp(&arp->ar_spa, &null_ip, ARP_PLEN) == 0 &&
+	    memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0 &&
+	    memcmp(&arp->ar_sha, NetOurEther, ARP_HLEN) != 0) {
 		target_ip_conflict = 1;
 	}
 
diff --git a/net/net.c b/net/net.c
index df94789..7663b9c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -271,7 +271,8 @@
 #endif
 		env_changed_id = env_id;
 	}
-	memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+	if (eth_get_dev())
+		memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
 
 	return;
 }
diff --git a/net/nfs.c b/net/nfs.c
index 7f2393f..381b75f 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -37,10 +37,14 @@
 # define NFS_TIMEOUT CONFIG_NFS_TIMEOUT
 #endif
 
+#define NFS_RPC_ERR	1
+#define NFS_RPC_DROP	124
+
 static int fs_mounted;
 static unsigned long rpc_id;
 static int nfs_offset = -1;
 static int nfs_len;
+static ulong nfs_timeout = NFS_TIMEOUT;
 
 static char dirfh[NFS_FHSIZE];	/* file handle of directory */
 static char filefh[NFS_FHSIZE]; /* file handle of kernel image */
@@ -399,8 +403,10 @@
 
 	debug("%s\n", __func__);
 
-	if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-		return -1;
+	if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+		return -NFS_RPC_ERR;
+	else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+		return -NFS_RPC_DROP;
 
 	if (rpc_pkt.u.reply.rstatus  ||
 	    rpc_pkt.u.reply.verifier ||
@@ -428,8 +434,10 @@
 
 	memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-	if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-		return -1;
+	if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+		return -NFS_RPC_ERR;
+	else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+		return -NFS_RPC_DROP;
 
 	if (rpc_pkt.u.reply.rstatus  ||
 	    rpc_pkt.u.reply.verifier ||
@@ -452,8 +460,10 @@
 
 	memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-	if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-		return -1;
+	if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+		return -NFS_RPC_ERR;
+	else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+		return -NFS_RPC_DROP;
 
 	if (rpc_pkt.u.reply.rstatus  ||
 	    rpc_pkt.u.reply.verifier ||
@@ -475,8 +485,10 @@
 
 	memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-	if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-		return -1;
+	if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+		return -NFS_RPC_ERR;
+	else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+		return -NFS_RPC_DROP;
 
 	if (rpc_pkt.u.reply.rstatus  ||
 	    rpc_pkt.u.reply.verifier ||
@@ -499,8 +511,10 @@
 
 	memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-	if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-		return -1;
+	if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+		return -NFS_RPC_ERR;
+	else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+		return -NFS_RPC_DROP;
 
 	if (rpc_pkt.u.reply.rstatus  ||
 	    rpc_pkt.u.reply.verifier ||
@@ -534,8 +548,10 @@
 
 	memcpy((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply));
 
-	if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-		return -1;
+	if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+		return -NFS_RPC_ERR;
+	else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+		return -NFS_RPC_DROP;
 
 	if (rpc_pkt.u.reply.rstatus  ||
 	    rpc_pkt.u.reply.verifier ||
@@ -574,7 +590,8 @@
 		NetStartAgain();
 	} else {
 		puts("T ");
-		NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
+		NetSetTimeout(nfs_timeout + NFS_TIMEOUT * NfsTimeoutCount,
+			      NfsTimeout);
 		NfsSend();
 	}
 }
@@ -583,6 +600,7 @@
 NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
 {
 	int rlen;
+	int reply;
 
 	debug("%s\n", __func__);
 
@@ -591,19 +609,24 @@
 
 	switch (NfsState) {
 	case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
-		rpc_lookup_reply(PROG_MOUNT, pkt, len);
+		if (rpc_lookup_reply(PROG_MOUNT, pkt, len) == -NFS_RPC_DROP)
+			break;
 		NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ;
 		NfsSend();
 		break;
 
 	case STATE_PRCLOOKUP_PROG_NFS_REQ:
-		rpc_lookup_reply(PROG_NFS, pkt, len);
+		if (rpc_lookup_reply(PROG_NFS, pkt, len) == -NFS_RPC_DROP)
+			break;
 		NfsState = STATE_MOUNT_REQ;
 		NfsSend();
 		break;
 
 	case STATE_MOUNT_REQ:
-		if (nfs_mount_reply(pkt, len)) {
+		reply = nfs_mount_reply(pkt, len);
+		if (reply == -NFS_RPC_DROP)
+			break;
+		else if (reply == -NFS_RPC_ERR) {
 			puts("*** ERROR: Cannot mount\n");
 			/* just to be sure... */
 			NfsState = STATE_UMOUNT_REQ;
@@ -615,7 +638,10 @@
 		break;
 
 	case STATE_UMOUNT_REQ:
-		if (nfs_umountall_reply(pkt, len)) {
+		reply = nfs_umountall_reply(pkt, len);
+		if (reply == -NFS_RPC_DROP)
+			break;
+		else if (reply == -NFS_RPC_ERR) {
 			puts("*** ERROR: Cannot umount\n");
 			net_set_state(NETLOOP_FAIL);
 		} else {
@@ -625,7 +651,10 @@
 		break;
 
 	case STATE_LOOKUP_REQ:
-		if (nfs_lookup_reply(pkt, len)) {
+		reply = nfs_lookup_reply(pkt, len);
+		if (reply == -NFS_RPC_DROP)
+			break;
+		else if (reply == -NFS_RPC_ERR) {
 			puts("*** ERROR: File lookup fail\n");
 			NfsState = STATE_UMOUNT_REQ;
 			NfsSend();
@@ -638,7 +667,10 @@
 		break;
 
 	case STATE_READLINK_REQ:
-		if (nfs_readlink_reply(pkt, len)) {
+		reply = nfs_readlink_reply(pkt, len);
+		if (reply == -NFS_RPC_DROP)
+			break;
+		else if (reply == -NFS_RPC_ERR) {
 			puts("*** ERROR: Symlink fail\n");
 			NfsState = STATE_UMOUNT_REQ;
 			NfsSend();
@@ -654,7 +686,7 @@
 
 	case STATE_READ_REQ:
 		rlen = nfs_read_reply(pkt, len);
-		NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
+		NetSetTimeout(nfs_timeout, NfsTimeout);
 		if (rlen > 0) {
 			nfs_offset += rlen;
 			NfsSend();
@@ -738,7 +770,7 @@
 	printf("\nLoad address: 0x%lx\n"
 		"Loading: *\b", load_addr);
 
-	NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
+	NetSetTimeout(nfs_timeout, NfsTimeout);
 	net_set_udp_handler(NfsHandler);
 
 	NfsTimeoutCount = 0;
diff --git a/net/tftp.c b/net/tftp.c
index 09790eb..6d333d5 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -446,8 +446,8 @@
 TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 	    unsigned len)
 {
-	ushort proto;
-	ushort *s;
+	__be16 proto;
+	__be16 *s;
 	int i;
 
 	if (dest != TftpOurPort) {
@@ -465,7 +465,7 @@
 		return;
 	len -= 2;
 	/* warning: don't use increment (++) in ntohs() macros!! */
-	s = (ushort *)pkt;
+	s = (__be16 *)pkt;
 	proto = *s++;
 	pkt = (uchar *)s;
 	switch (ntohs(proto)) {
@@ -556,7 +556,7 @@
 		if (len < 2)
 			return;
 		len -= 2;
-		TftpBlock = ntohs(*(ushort *)pkt);
+		TftpBlock = ntohs(*(__be16 *)pkt);
 
 		update_block_number();
 
@@ -644,9 +644,9 @@
 
 	case TFTP_ERROR:
 		printf("\nTFTP error: '%s' (%d)\n",
-		       pkt + 2, ntohs(*(ushort *)pkt));
+		       pkt + 2, ntohs(*(__be16 *)pkt));
 
-		switch (ntohs(*(ushort *)pkt)) {
+		switch (ntohs(*(__be16 *)pkt)) {
 		case TFTP_ERR_FILE_NOT_FOUND:
 		case TFTP_ERR_ACCESS_DENIED:
 			puts("Not retrying...\n");
diff --git a/spl/Makefile b/spl/Makefile
index d8fe948..01873de 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -98,6 +98,14 @@
 LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o
 endif
 
+ifneq ($(CONFIG_MX23)$(CONFIG_MX35),)
+LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o
+endif
+
+ifeq ($(SOC),exynos)
+LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
+endif
+
 # Add GCC lib
 ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
 PLATFORM_LIBGCC = $(SPLTREE)/arch/$(ARCH)/lib/libgcc.o
diff --git a/test/image/test-fit.py b/test/image/test-fit.py
index c4e8211..aad9f59 100755
--- a/test/image/test-fit.py
+++ b/test/image/test-fit.py
@@ -272,12 +272,13 @@
     test_name = name
     print name
 
-def fail(msg):
+def fail(msg, stdout):
     """Raise an error with a helpful failure message
 
     Args:
         msg: Message to display
     """
+    print stdout
     raise ValueError("Test '%s' failed: %s" % (test_name, msg))
 
 def run_fit_test(mkimage, u_boot):
@@ -341,11 +342,11 @@
     set_test('Kernel load')
     stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
     if read_file(kernel) != read_file(kernel_out):
-        fail('Kernel not loaded')
+        fail('Kernel not loaded', stdout)
     if read_file(control_dtb) == read_file(fdt_out):
-        fail('FDT loaded but should be ignored')
+        fail('FDT loaded but should be ignored', stdout)
     if read_file(ramdisk) == read_file(ramdisk_out):
-        fail('Ramdisk loaded but should not be')
+        fail('Ramdisk loaded but should not be', stdout)
 
     # Find out the offset in the FIT where U-Boot has found the FDT
     line = find_matching(stdout, 'Booting using the fdt blob at ')
@@ -357,7 +358,7 @@
     real_fit_offset = data.find(fdt_magic, 4)
     if fit_offset != real_fit_offset:
         fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
-                (fit_offset, real_fit_offset))
+                (fit_offset, real_fit_offset), stdout)
 
     # Now a kernel and an FDT
     set_test('Kernel + FDT load')
@@ -365,11 +366,11 @@
     fit = make_fit(mkimage, params)
     stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
     if read_file(kernel) != read_file(kernel_out):
-        fail('Kernel not loaded')
+        fail('Kernel not loaded', stdout)
     if read_file(control_dtb) != read_file(fdt_out):
-        fail('FDT not loaded')
+        fail('FDT not loaded', stdout)
     if read_file(ramdisk) == read_file(ramdisk_out):
-        fail('Ramdisk loaded but should not be')
+        fail('Ramdisk loaded but should not be', stdout)
 
     # Try a ramdisk
     set_test('Kernel + FDT + Ramdisk load')
@@ -378,7 +379,7 @@
     fit = make_fit(mkimage, params)
     stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
     if read_file(ramdisk) != read_file(ramdisk_out):
-        fail('Ramdisk not loaded')
+        fail('Ramdisk not loaded', stdout)
 
 def run_tests():
     """Parse options, run the FIT tests and print the result"""
diff --git a/test/trace/test-trace.sh b/test/trace/test-trace.sh
new file mode 100755
index 0000000..696a396
--- /dev/null
+++ b/test/trace/test-trace.sh
@@ -0,0 +1,89 @@
+# Copyright (c) 2013 The Chromium OS Authors.
+#
+# 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
+#
+
+# Simple test script for tracing with sandbox
+
+OUTPUT_DIR=sandbox
+TRACE_OPT="FTRACE=1"
+
+fail() {
+	echo "Test failed: $1"
+	if [ -n ${tmp} ]; then
+		rm ${tmp}
+	fi
+	exit 1
+}
+
+build_uboot() {
+	echo "Build sandbox"
+	OPTS="O=${OUTPUT_DIR} ${TRACE_OPT}"
+	NUM_CPUS=$(grep -c processor /proc/cpuinfo)
+	make ${OPTS} sandbox_config
+	make ${OPTS} -s -j${NUM_CPUS}
+}
+
+run_trace() {
+	echo "Run trace"
+	./${OUTPUT_DIR}/u-boot <<END
+	trace stats
+	hash sha256 0 10000
+	trace pause
+	trace stats
+	hash sha256 0 10000
+	trace stats
+	trace resume
+	hash sha256 0 10000
+	trace pause
+	trace stats
+	reset
+END
+}
+
+check_results() {
+	echo "Check results"
+
+	# Expect sha256 to run 3 times, so we see the string 6 times
+	if [ $(grep -c sha256 ${tmp}) -ne 6 ]; then
+		fail "sha256 error"
+	fi
+
+	# 4 sets of results (output of 'trace stats')
+	if [ $(grep -c "traced function calls" ${tmp}) -ne 4 ]; then
+		fail "trace output error"
+	fi
+
+	# Check trace counts. We expect to see an increase in the number of
+	# traced function calls between each 'trace stats' command, except
+	# between calls 2 and 3, where tracing is paused.
+	# This code gets the sign of the difference between each number and
+	# its predecessor.
+	counts="$(tr -d , <${tmp} | awk '/traced function calls/ { diff = $1 - upto; upto = $1; printf "%d ", diff < 0 ? -1 : (diff > 0 ? 1 : 0)}')"
+
+	if [ "${counts}" != "1 1 0 1 " ]; then
+		fail "trace collection error: ${counts}"
+	fi
+}
+
+echo "Simple trace test / sanity check using sandbox"
+echo
+tmp="$(tempfile)"
+build_uboot
+run_trace >${tmp}
+check_results ${tmp}
+rm ${tmp}
+echo "Test passed"
diff --git a/test/vboot/.gitignore b/test/vboot/.gitignore
new file mode 100644
index 0000000..4631242
--- /dev/null
+++ b/test/vboot/.gitignore
@@ -0,0 +1,3 @@
+/*.dtb
+/test.fit
+/dev-keys
diff --git a/test/vboot/sandbox-kernel.dts b/test/vboot/sandbox-kernel.dts
new file mode 100644
index 0000000..a1e853c
--- /dev/null
+++ b/test/vboot/sandbox-kernel.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	model = "Sandbox Verified Boot Test";
+	compatible = "sandbox";
+
+};
diff --git a/test/vboot/sandbox-u-boot.dts b/test/vboot/sandbox-u-boot.dts
new file mode 100644
index 0000000..a1e853c
--- /dev/null
+++ b/test/vboot/sandbox-u-boot.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	model = "Sandbox Verified Boot Test";
+	compatible = "sandbox";
+
+};
diff --git a/test/vboot/sign-configs.its b/test/vboot/sign-configs.its
new file mode 100644
index 0000000..db2ed79
--- /dev/null
+++ b/test/vboot/sign-configs.its
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel@1 {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			hash@1 {
+				algo = "sha1";
+			};
+		};
+		fdt@1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash@1 {
+				algo = "sha1";
+			};
+		};
+	};
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+			signature@1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/test/vboot/sign-images.its b/test/vboot/sign-images.its
new file mode 100644
index 0000000..f69326a
--- /dev/null
+++ b/test/vboot/sign-images.its
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel@1 {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			signature@1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+			};
+		};
+		fdt@1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			signature@1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+			};
+		};
+	};
+	configurations {
+		default = "conf@1";
+		conf@1 {
+			kernel = "kernel@1";
+			fdt = "fdt@1";
+		};
+	};
+};
diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh
new file mode 100755
index 0000000..c3cfade
--- /dev/null
+++ b/test/vboot/vboot_test.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+#
+# Copyright (c) 2013, Google Inc.
+#
+# Simple Verified Boot Test Script
+#
+# 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
+
+set -e
+
+# Run U-Boot and report the result
+# Args:
+#	$1:	Test message
+run_uboot() {
+	echo -n "Test Verified Boot Run: $1: "
+	${uboot} -d sandbox-u-boot.dtb >${tmp} -c '
+sb load host 0 100 test.fit;
+fdt addr 100;
+bootm 100;
+reset'
+	if ! grep -q "$2" ${tmp}; then
+		echo
+		echo "Verified boot key check failed, output follows:"
+		cat ${tmp}
+		false
+	else
+		echo "OK"
+	fi
+}
+
+echo "Simple Verified Boot Test"
+echo "========================="
+echo
+echo "Please see doc/uImage.FIT/verified-boot.txt for more information"
+echo
+
+err=0
+tmp=/tmp/vboot_test.$$
+
+dir=$(dirname $0)
+
+if [ -z ${O} ]; then
+	O=.
+fi
+O=$(readlink -f ${O})
+
+dtc="-I dts -O dtb -p 2000"
+uboot="${O}/u-boot"
+mkimage="${O}/tools/mkimage"
+keys="${dir}/dev-keys"
+echo ${mkimage} -D "${dtc}"
+
+echo "Build keys"
+mkdir -p ${keys}
+
+# Create an RSA key pair
+openssl genrsa -F4 -out ${keys}/dev.key 2048 2>/dev/null
+
+# Create a certificate containing the public key
+openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
+
+pushd ${dir} >/dev/null
+
+# Compile our device tree files for kernel and U-Boot (CONFIG_OF_CONTROL)
+dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
+dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
+
+# Create a number kernel image with zeroes
+head -c 5000 /dev/zero >test-kernel.bin
+
+# Build the FIT, but don't sign anything yet
+echo Build FIT with signed images
+${mkimage} -D "${dtc}" -f sign-images.its test.fit >${tmp}
+
+run_uboot "unsigned signatures:" "dev-"
+
+# Sign images with our dev keys
+echo Sign images
+${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+
+run_uboot "signed images" "dev+"
+
+
+# Create a fresh .dtb without the public keys
+dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
+
+echo Build FIT with signed configuration
+${mkimage} -D "${dtc}" -f sign-configs.its test.fit >${tmp}
+
+run_uboot "unsigned config" "sha1+ OK"
+
+# Sign images with our dev keys
+echo Sign images
+${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+
+run_uboot "signed config" "dev+"
+
+# Increment the first byte of the signature, which should cause failure
+sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value)
+newbyte=$(printf %x $((0x${sig:0:2} + 1)))
+sig="${newbyte} ${sig:2}"
+fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
+
+run_uboot "signed config with bad hash" "Bad Data Hash"
+
+popd >/dev/null
+
+echo
+if ${ok}; then
+	echo "Test passed"
+else
+	echo "Test failed"
+fi
diff --git a/tools/.gitignore b/tools/.gitignore
index 9bce719..a7fee26 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -9,6 +9,7 @@
 /mxsboot
 /ncb
 /ncp
+/proftool
 /ubsha1
 /xway-swap-bytes
 /*.exe
diff --git a/tools/Makefile b/tools/Makefile
index 4630f03..46159b2 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -74,11 +74,13 @@
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
 BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
+BIN_FILES-y += proftool(SFX)
 
 # Source files which exist outside the tools directory
 EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
 EXT_OBJ_FILES-y += common/image.o
 EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o
+EXT_OBJ_FILES-y += common/image-sig.o
 EXT_OBJ_FILES-y += lib/crc32.o
 EXT_OBJ_FILES-y += lib/md5.o
 EXT_OBJ_FILES-y += lib/sha1.o
@@ -87,6 +89,7 @@
 OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o
 OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o
 NOPED_OBJ_FILES-y += default_image.o
+NOPED_OBJ_FILES-y += proftool.o
 OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o
 NOPED_OBJ_FILES-y += fit_image.o
 OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o
@@ -122,6 +125,9 @@
 LIBFDT_OBJ_FILES-y += fdt_strerror.o
 LIBFDT_OBJ_FILES-y += fdt_wip.o
 
+# RSA objects
+RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o
+
 # Generated LCD/video logo
 LOGO_H = $(OBJTREE)/include/bmp_logo.h
 LOGO_DATA_H = $(OBJTREE)/include/bmp_logo_data.h
@@ -149,8 +155,14 @@
 HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c))
 HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c))
 HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c))
+HOSTSRCS += $(addprefix $(SRCTREE)/lib/rsa/,$(RSA_OBJ_FILES-y:.o=.c))
 BINS	:= $(addprefix $(obj),$(sort $(BIN_FILES-y)))
 LIBFDT_OBJS	:= $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y))
+RSA_OBJS	:= $(addprefix $(obj),$(RSA_OBJ_FILES-y))
+
+# We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host
+FIT_SIG_OBJ_FILES	:= image-sig.o
+FIT_SIG_OBJS		:= $(addprefix $(obj),$(FIT_SIG_OBJ_FILES))
 
 HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y))
 NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y))
@@ -180,6 +192,10 @@
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
 
+$(obj)proftool(SFX):	$(obj)proftool.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+	$(HOSTSTRIP) $@
+
 $(obj)envcrc$(SFX):	$(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 
@@ -207,6 +223,7 @@
 			$(obj)image-fit.o \
 			$(obj)image.o \
 			$(obj)image-host.o \
+			$(FIT_SIG_OBJS) \
 			$(obj)imximage.o \
 			$(obj)kwbimage.o \
 			$(obj)pblimage.o \
@@ -216,8 +233,9 @@
 			$(obj)omapimage.o \
 			$(obj)sha1.o \
 			$(obj)ublimage.o \
-			$(LIBFDT_OBJS)
-	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+			$(LIBFDT_OBJS) \
+			$(RSA_OBJS)
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS)
 	$(HOSTSTRIP) $@
 
 $(obj)mk$(BOARD)spl$(SFX):	$(obj)mkexynosspl.o
@@ -253,6 +271,9 @@
 $(obj)%.o: $(SRCTREE)/lib/libfdt/%.c
 	$(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
 
+$(obj)%.o: $(SRCTREE)/lib/rsa/%.c
+	$(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+
 subdirs:
 ifeq ($(TOOLSUBDIRS),)
 	@:
diff --git a/tools/fit_image.c b/tools/fit_image.c
index cc123dd..281c2bd 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -105,9 +105,11 @@
 {
 	char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
 	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
-	int tfd;
+	int tfd, destfd = 0;
+	void *dest_blob = NULL;
 	struct stat sbuf;
 	void *ptr;
+	off_t destfd_size = 0;
 
 	/* Flattened Image Tree (FIT) format  handling */
 	debug ("FIT format handling\n");
@@ -122,29 +124,44 @@
 	}
 	sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
 
-	/* dtc -I dts -O dtb -p 500 datafile > tmpfile */
-	sprintf (cmd, "%s %s %s > %s",
-		MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
-	debug ("Trying to execute \"%s\"\n", cmd);
+	/* We either compile the source file, or use the existing FIT image */
+	if (params->datafile) {
+		/* dtc -I dts -O dtb -p 500 datafile > tmpfile */
+		snprintf(cmd, sizeof(cmd), "%s %s %s > %s",
+			 MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
+		debug("Trying to execute \"%s\"\n", cmd);
+	} else {
+		snprintf(cmd, sizeof(cmd), "cp %s %s",
+			 params->imagefile, tmpfile);
+	}
 	if (system (cmd) == -1) {
 		fprintf (stderr, "%s: system(%s) failed: %s\n",
 				params->cmdname, cmd, strerror(errno));
 		goto err_system;
 	}
 
+	if (params->keydest) {
+		destfd = mmap_fdt(params, params->keydest, &dest_blob, &sbuf);
+		if (destfd < 0)
+			goto err_keydest;
+		destfd_size = sbuf.st_size;
+	}
+
 	tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf);
 	if (tfd < 0)
 		goto err_mmap;
 
 	/* set hashes for images in the blob */
-	if (fit_add_verification_data(ptr)) {
-		fprintf (stderr, "%s Can't add hashes to FIT blob",
-				params->cmdname);
+	if (fit_add_verification_data(params->keydir,
+				      dest_blob, ptr, params->comment,
+				      params->require_keys)) {
+		fprintf(stderr, "%s Can't add hashes to FIT blob\n",
+			params->cmdname);
 		goto err_add_hashes;
 	}
 
-	/* add a timestamp at offset 0 i.e., root  */
-	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
+	/* for first image creation, add a timestamp at offset 0 i.e., root  */
+	if (params->datafile && fit_set_timestamp(ptr, 0, sbuf.st_mtime)) {
 		fprintf (stderr, "%s: Can't add image timestamp\n",
 				params->cmdname);
 		goto err_add_timestamp;
@@ -153,6 +170,10 @@
 
 	munmap ((void *)ptr, sbuf.st_size);
 	close (tfd);
+	if (dest_blob) {
+		munmap(dest_blob, destfd_size);
+		close(destfd);
+	}
 
 	if (rename (tmpfile, params->imagefile) == -1) {
 		fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
@@ -168,6 +189,9 @@
 err_add_hashes:
 	munmap(ptr, sbuf.st_size);
 err_mmap:
+	if (dest_blob)
+		munmap(dest_blob, destfd_size);
+err_keydest:
 err_system:
 	unlink(tmpfile);
 	return -1;
diff --git a/tools/image-host.c b/tools/image-host.c
index d944d0f..932384b 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -26,12 +26,8 @@
  */
 
 #include "mkimage.h"
-#include <bootstage.h>
 #include <image.h>
-#include <sha1.h>
-#include <time.h>
-#include <u-boot/crc.h>
-#include <u-boot/md5.h>
+#include <version.h>
 
 /**
  * fit_set_hash_value - set hash value in requested has node
@@ -108,9 +104,165 @@
 }
 
 /**
- * fit_image_add_verification_data() - calculate/set hash data for image node
+ * fit_image_write_sig() - write the signature to a FIT
  *
- * This adds hash values for a component image node.
+ * This writes the signature and signer data to the FIT.
+ *
+ * @fit: pointer to the FIT format image header
+ * @noffset: hash node offset
+ * @value: signature value to be set
+ * @value_len: signature value length
+ * @comment: Text comment to write (NULL for none)
+ *
+ * returns
+ *     0, on success
+ *     -FDT_ERR_..., on failure
+ */
+static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
+		int value_len, const char *comment, const char *region_prop,
+		int region_proplen)
+{
+	int string_size;
+	int ret;
+
+	/*
+	 * Get the current string size, before we update the FIT and add
+	 * more
+	 */
+	string_size = fdt_size_dt_strings(fit);
+
+	ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
+	if (!ret) {
+		ret = fdt_setprop_string(fit, noffset, "signer-name",
+					 "mkimage");
+	}
+	if (!ret) {
+		ret = fdt_setprop_string(fit, noffset, "signer-version",
+				  PLAIN_VERSION);
+	}
+	if (comment && !ret)
+		ret = fdt_setprop_string(fit, noffset, "comment", comment);
+	if (!ret)
+		ret = fit_set_timestamp(fit, noffset, time(NULL));
+	if (region_prop && !ret) {
+		uint32_t strdata[2];
+
+		ret = fdt_setprop(fit, noffset, "hashed-nodes",
+				   region_prop, region_proplen);
+		strdata[0] = 0;
+		strdata[1] = cpu_to_fdt32(string_size);
+		if (!ret) {
+			ret = fdt_setprop(fit, noffset, "hashed-strings",
+					  strdata, sizeof(strdata));
+		}
+	}
+
+	return ret;
+}
+
+static int fit_image_setup_sig(struct image_sign_info *info,
+		const char *keydir, void *fit, const char *image_name,
+		int noffset, const char *require_keys)
+{
+	const char *node_name;
+	char *algo_name;
+
+	node_name = fit_get_name(fit, noffset, NULL);
+	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+		printf("Can't get algo property for '%s' signature node in '%s' image node\n",
+		       node_name, image_name);
+		return -1;
+	}
+
+	memset(info, '\0', sizeof(*info));
+	info->keydir = keydir;
+	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	info->fit = fit;
+	info->node_offset = noffset;
+	info->algo = image_get_sig_algo(algo_name);
+	info->require_keys = require_keys;
+	if (!info->algo) {
+		printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
+		       algo_name, node_name, image_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_image_process_sig- Process a single subnode of the images/ node
+ *
+ * Check each subnode and process accordingly. For signature nodes we
+ * generate a signed hash of the supplised data and store it in the node.
+ *
+ * @keydir:	Directory containing keys to use for signing
+ * @keydest:	Destination FDT blob to write public keys into
+ * @fit:	pointer to the FIT format image header
+ * @image_name:	name of image being processes (used to display errors)
+ * @noffset:	subnode offset
+ * @data:	data to process
+ * @size:	size of data in bytes
+ * @comment:	Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ * @return 0 if ok, -1 on error
+ */
+static int fit_image_process_sig(const char *keydir, void *keydest,
+		void *fit, const char *image_name,
+		int noffset, const void *data, size_t size,
+		const char *comment, int require_keys)
+{
+	struct image_sign_info info;
+	struct image_region region;
+	const char *node_name;
+	uint8_t *value;
+	uint value_len;
+	int ret;
+
+	if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
+				require_keys ? "image" : NULL))
+		return -1;
+
+	node_name = fit_get_name(fit, noffset, NULL);
+	region.data = data;
+	region.size = size;
+	ret = info.algo->sign(&info, &region, 1, &value, &value_len);
+	if (ret) {
+		printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
+		       node_name, image_name, ret);
+
+		/* We allow keys to be missing */
+		if (ret == -ENOENT)
+			return 0;
+		return -1;
+	}
+
+	ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
+			NULL, 0);
+	if (ret) {
+		printf("Can't write signature for '%s' signature node in '%s' image node: %s\n",
+		       node_name, image_name, fdt_strerror(ret));
+		return -1;
+	}
+	free(value);
+
+	/* Get keyname again, as FDT has changed and invalidated our pointer */
+	info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+
+	/* Write the public key into the supplied FDT file */
+	if (keydest && info.algo->add_verify_data(&info, keydest)) {
+		printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
+		       node_name, image_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_image_add_verification_data() - calculate/set verig. data for image node
+ *
+ * This adds hash and signature values for an component image node.
  *
  * All existing hash subnodes are checked, if algorithm property is set to
  * one of the supported hash algorithms, hash value is computed and
@@ -133,11 +285,17 @@
  *
  * For signature details, please see doc/uImage.FIT/signature.txt
  *
+ * @keydir	Directory containing *.key and *.crt files (or NULL)
+ * @keydest	FDT Blob to write public keys into (NULL if none)
  * @fit:	Pointer to the FIT format image header
  * @image_noffset: Requested component image node
+ * @comment:	Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
  * @return: 0 on success, <0 on failure
  */
-int fit_image_add_verification_data(void *fit, int image_noffset)
+int fit_image_add_verification_data(const char *keydir, void *keydest,
+		void *fit, int image_noffset, const char *comment,
+		int require_keys)
 {
 	const char *image_name;
 	const void *data;
@@ -169,6 +327,12 @@
 			     strlen(FIT_HASH_NODENAME))) {
 			ret = fit_image_process_hash(fit, image_name, noffset,
 						data, size);
+		} else if (IMAGE_ENABLE_SIGN && keydir &&
+			   !strncmp(node_name, FIT_SIG_NODENAME,
+				strlen(FIT_SIG_NODENAME))) {
+			ret = fit_image_process_sig(keydir, keydest,
+				fit, image_name, noffset, data, size,
+				comment, require_keys);
 		}
 		if (ret)
 			return -1;
@@ -177,9 +341,326 @@
 	return 0;
 }
 
-int fit_add_verification_data(void *fit)
+struct strlist {
+	int count;
+	char **strings;
+};
+
+static void strlist_init(struct strlist *list)
 {
-	int images_noffset;
+	memset(list, '\0', sizeof(*list));
+}
+
+static void strlist_free(struct strlist *list)
+{
+	int i;
+
+	for (i = 0; i < list->count; i++)
+		free(list->strings[i]);
+	free(list->strings);
+}
+
+static int strlist_add(struct strlist *list, const char *str)
+{
+	char *dup;
+
+	dup = strdup(str);
+	list->strings = realloc(list->strings,
+				(list->count + 1) * sizeof(char *));
+	if (!list || !str)
+		return -1;
+	list->strings[list->count++] = dup;
+
+	return 0;
+}
+
+static const char *fit_config_get_image_list(void *fit, int noffset,
+		int *lenp, int *allow_missingp)
+{
+	static const char default_list[] = FIT_KERNEL_PROP "\0"
+			FIT_FDT_PROP;
+	const char *prop;
+
+	/* If there is an "image" property, use that */
+	prop = fdt_getprop(fit, noffset, "sign-images", lenp);
+	if (prop) {
+		*allow_missingp = 0;
+		return *lenp ? prop : NULL;
+	}
+
+	/* Default image list */
+	*allow_missingp = 1;
+	*lenp = sizeof(default_list);
+
+	return default_list;
+}
+
+static int fit_config_get_hash_list(void *fit, int conf_noffset,
+				    int sig_offset, struct strlist *node_inc)
+{
+	int allow_missing;
+	const char *prop, *iname, *end;
+	const char *conf_name, *sig_name;
+	char name[200], path[200];
+	int image_count;
+	int ret, len;
+
+	conf_name = fit_get_name(fit, conf_noffset, NULL);
+	sig_name = fit_get_name(fit, sig_offset, NULL);
+
+	/*
+	 * Build a list of nodes we need to hash. We always need the root
+	 * node and the configuration.
+	 */
+	strlist_init(node_inc);
+	snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
+	if (strlist_add(node_inc, "/") ||
+	    strlist_add(node_inc, name))
+		goto err_mem;
+
+	/* Get a list of images that we intend to sign */
+	prop = fit_config_get_image_list(fit, conf_noffset, &len,
+					&allow_missing);
+	if (!prop)
+		return 0;
+
+	/* Locate the images */
+	end = prop + len;
+	image_count = 0;
+	for (iname = prop; iname < end; iname += strlen(iname) + 1) {
+		int noffset;
+		int image_noffset;
+		int hash_count;
+
+		image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
+						       iname);
+		if (image_noffset < 0) {
+			printf("Failed to find image '%s' in  configuration '%s/%s'\n",
+			       iname, conf_name, sig_name);
+			if (allow_missing)
+				continue;
+
+			return -ENOENT;
+		}
+
+		ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
+		if (ret < 0)
+			goto err_path;
+		if (strlist_add(node_inc, path))
+			goto err_mem;
+
+		snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
+			 conf_name);
+
+		/* Add all this image's hashes */
+		hash_count = 0;
+		for (noffset = fdt_first_subnode(fit, image_noffset);
+		     noffset >= 0;
+		     noffset = fdt_next_subnode(fit, noffset)) {
+			const char *name = fit_get_name(fit, noffset, NULL);
+
+			if (strncmp(name, FIT_HASH_NODENAME,
+				    strlen(FIT_HASH_NODENAME)))
+				continue;
+			ret = fdt_get_path(fit, noffset, path, sizeof(path));
+			if (ret < 0)
+				goto err_path;
+			if (strlist_add(node_inc, path))
+				goto err_mem;
+			hash_count++;
+		}
+
+		if (!hash_count) {
+			printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
+			       conf_name, sig_name, iname);
+			return -ENOMSG;
+		}
+
+		image_count++;
+	}
+
+	if (!image_count) {
+		printf("Failed to find any images for configuration '%s/%s'\n",
+		       conf_name, sig_name);
+		return -ENOMSG;
+	}
+
+	return 0;
+
+err_mem:
+	printf("Out of memory processing configuration '%s/%s'\n", conf_name,
+	       sig_name);
+	return -ENOMEM;
+
+err_path:
+	printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
+	       iname, conf_name, sig_name, fdt_strerror(ret));
+	return -ENOENT;
+}
+
+static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
+		struct image_region **regionp, int *region_countp,
+		char **region_propp, int *region_proplen)
+{
+	char * const exc_prop[] = {"data"};
+	struct strlist node_inc;
+	struct image_region *region;
+	struct fdt_region fdt_regions[100];
+	const char *conf_name, *sig_name;
+	char path[200];
+	int count, i;
+	char *region_prop;
+	int ret, len;
+
+	conf_name = fit_get_name(fit, conf_noffset, NULL);
+	sig_name = fit_get_name(fit, conf_noffset, NULL);
+	debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
+
+	/* Get a list of nodes we want to hash */
+	ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
+	if (ret)
+		return ret;
+
+	/* Get a list of regions to hash */
+	count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
+			exc_prop, ARRAY_SIZE(exc_prop),
+			fdt_regions, ARRAY_SIZE(fdt_regions),
+			path, sizeof(path), 1);
+	if (count < 0) {
+		printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
+		       sig_name, fdt_strerror(ret));
+		return -EIO;
+	}
+	if (count == 0) {
+		printf("No data to hash for configuration '%s/%s': %s\n",
+		       conf_name, sig_name, fdt_strerror(ret));
+		return -EINVAL;
+	}
+
+	/* Build our list of data blocks */
+	region = fit_region_make_list(fit, fdt_regions, count, NULL);
+	if (!region) {
+		printf("Out of memory hashing configuration '%s/%s'\n",
+		       conf_name, sig_name);
+		return -ENOMEM;
+	}
+
+	/* Create a list of all hashed properties */
+	debug("Hash nodes:\n");
+	for (i = len = 0; i < node_inc.count; i++) {
+		debug("   %s\n", node_inc.strings[i]);
+		len += strlen(node_inc.strings[i]) + 1;
+	}
+	region_prop = malloc(len);
+	if (!region_prop) {
+		printf("Out of memory setting up regions for configuration '%s/%s'\n",
+		       conf_name, sig_name);
+		return -ENOMEM;
+	}
+	for (i = len = 0; i < node_inc.count;
+	     len += strlen(node_inc.strings[i]) + 1, i++)
+		strcpy(region_prop + len, node_inc.strings[i]);
+	strlist_free(&node_inc);
+
+	*region_countp = count;
+	*regionp = region;
+	*region_propp = region_prop;
+	*region_proplen = len;
+
+	return 0;
+}
+
+static int fit_config_process_sig(const char *keydir, void *keydest,
+		void *fit, const char *conf_name, int conf_noffset,
+		int noffset, const char *comment, int require_keys)
+{
+	struct image_sign_info info;
+	const char *node_name;
+	struct image_region *region;
+	char *region_prop;
+	int region_proplen;
+	int region_count;
+	uint8_t *value;
+	uint value_len;
+	int ret;
+
+	node_name = fit_get_name(fit, noffset, NULL);
+	if (fit_config_get_data(fit, conf_noffset, noffset, &region,
+				&region_count, &region_prop, &region_proplen))
+		return -1;
+
+	if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
+				require_keys ? "conf" : NULL))
+		return -1;
+
+	ret = info.algo->sign(&info, region, region_count, &value, &value_len);
+	free(region);
+	if (ret) {
+		printf("Failed to sign '%s' signature node in '%s' conf node\n",
+		       node_name, conf_name);
+
+		/* We allow keys to be missing */
+		if (ret == -ENOENT)
+			return 0;
+		return -1;
+	}
+
+	if (fit_image_write_sig(fit, noffset, value, value_len, comment,
+				region_prop, region_proplen)) {
+		printf("Can't write signature for '%s' signature node in '%s' conf node\n",
+		       node_name, conf_name);
+		return -1;
+	}
+	free(value);
+	free(region_prop);
+
+	/* Get keyname again, as FDT has changed and invalidated our pointer */
+	info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+
+	/* Write the public key into the supplied FDT file */
+	if (keydest && info.algo->add_verify_data(&info, keydest)) {
+		printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
+		       node_name, conf_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_config_add_verification_data(const char *keydir, void *keydest,
+		void *fit, int conf_noffset, const char *comment,
+		int require_keys)
+{
+	const char *conf_name;
+	int noffset;
+
+	conf_name = fit_get_name(fit, conf_noffset, NULL);
+
+	/* Process all hash subnodes of the configuration node */
+	for (noffset = fdt_first_subnode(fit, conf_noffset);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(fit, noffset)) {
+		const char *node_name;
+		int ret = 0;
+
+		node_name = fit_get_name(fit, noffset, NULL);
+		if (!strncmp(node_name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_config_process_sig(keydir, keydest,
+				fit, conf_name, conf_noffset, noffset, comment,
+				require_keys);
+		}
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+			      const char *comment, int require_keys)
+{
+	int images_noffset, confs_noffset;
 	int noffset;
 	int ret;
 
@@ -199,7 +680,31 @@
 		 * Direct child node of the images parent node,
 		 * i.e. component image node.
 		 */
-		ret = fit_image_add_verification_data(fit, noffset);
+		ret = fit_image_add_verification_data(keydir, keydest,
+				fit, noffset, comment, require_keys);
+		if (ret)
+			return ret;
+	}
+
+	/* If there are no keys, we can't sign configurations */
+	if (!IMAGE_ENABLE_SIGN || !keydir)
+		return 0;
+
+	/* Find configurations parent node offset */
+	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+	if (confs_noffset < 0) {
+		printf("Can't find images parent node '%s' (%s)\n",
+		       FIT_IMAGES_PATH, fdt_strerror(confs_noffset));
+		return -ENOENT;
+	}
+
+	/* Process its subnodes, print out component images details */
+	for (noffset = fdt_first_subnode(fit, confs_noffset);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(fit, noffset)) {
+		ret = fit_config_add_verification_data(keydir, keydest,
+						       fit, noffset, comment,
+						       require_keys);
 		if (ret)
 			return ret;
 	}
diff --git a/tools/mkimage.c b/tools/mkimage.c
index e43b09f..d312844 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -183,6 +183,11 @@
 					genimg_get_arch_id (*++argv)) < 0)
 					usage ();
 				goto NXTARG;
+			case 'c':
+				if (--argc <= 0)
+					usage();
+				params.comment = *++argv;
+				goto NXTARG;
 			case 'C':
 				if ((--argc <= 0) ||
 					(params.comp =
@@ -240,19 +245,34 @@
 			case 'f':
 				if (--argc <= 0)
 					usage ();
+				params.datafile = *++argv;
+				/* no break */
+			case 'F':
 				/*
 				 * The flattened image tree (FIT) format
 				 * requires a flattened device tree image type
 				 */
 				params.type = IH_TYPE_FLATDT;
-				params.datafile = *++argv;
 				params.fflag = 1;
 				goto NXTARG;
+			case 'k':
+				if (--argc <= 0)
+					usage();
+				params.keydir = *++argv;
+				goto NXTARG;
+			case 'K':
+				if (--argc <= 0)
+					usage();
+				params.keydest = *++argv;
+				goto NXTARG;
 			case 'n':
 				if (--argc <= 0)
 					usage ();
 				params.imagename = *++argv;
 				goto NXTARG;
+			case 'r':
+				params.require_keys = 1;
+				break;
 			case 'R':
 				if (--argc <= 0)
 					usage();
@@ -623,8 +643,20 @@
 			 "          -d ==> use image data from 'datafile'\n"
 			 "          -x ==> set XIP (execute in place)\n",
 		params.cmdname);
-	fprintf (stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n",
+	fprintf(stderr, "       %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n",
 		params.cmdname);
+	fprintf(stderr, "          -D => set options for device tree compiler\n"
+			"          -f => input filename for FIT source\n");
+#ifdef CONFIG_FIT_SIGNATURE
+	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n"
+			"          -k => set directory containing private keys\n"
+			"          -K => write public keys to this .dtb file\n"
+			"          -c => add comment in signature node\n"
+			"          -F => re-sign existing FIT image\n"
+			"          -r => mark keys used as 'required' in dtb\n");
+#else
+	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
+#endif
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
 
diff --git a/tools/mkimage.h b/tools/mkimage.h
index 03c6c8f..1d9984e 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -87,6 +87,10 @@
 	char *datafile;
 	char *imagefile;
 	char *cmdname;
+	const char *keydir;	/* Directory holding private keys */
+	const char *keydest;	/* Destination .dtb for public key */
+	const char *comment;	/* Comment to add to signature node */
+	int require_keys;	/* 1 to mark signing keys as 'required' */
 };
 
 /*
diff --git a/tools/pblimage.c b/tools/pblimage.c
index 508a747..5f39dc5 100644
--- a/tools/pblimage.c
+++ b/tools/pblimage.c
@@ -26,18 +26,14 @@
 #include "pblimage.h"
 
 /*
- * The PBL can load up to 64 bytes at a time, so we split the U-Boot
- * image into 64 byte chunks. PBL needs a command for each piece, of
- * the form "81xxxxxx", where "xxxxxx" is the offset. SYS_TEXT_BASE
- * is 0xFFF80000 for PBL boot, and PBL only cares about low 24-bit,
- * so it starts from 0x81F80000.
+ * Initialize to an invalid value.
  */
-static uint32_t next_pbl_cmd = 0x81F80000;
+static uint32_t next_pbl_cmd = 0x82000000;
 /*
  * need to store all bytes in memory for calculating crc32, then write the
  * bytes to image file for PBL boot.
  */
-static unsigned char mem_buf[600000];
+static unsigned char mem_buf[1000000];
 static unsigned char *pmem_buf = mem_buf;
 static int pbl_size;
 static char *fname = "Unknown";
@@ -52,6 +48,27 @@
 
 #define ENDIANNESS ((char)endian_test.l)
 
+/*
+ * The PBL can load up to 64 bytes at a time, so we split the U-Boot
+ * image into 64 byte chunks. PBL needs a command for each piece, of
+ * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the
+ * start offset by subtracting the size of the u-boot image from the
+ * top of the allowable 24-bit range.
+ */
+static void init_next_pbl_cmd(FILE *fp_uboot)
+{
+	struct stat st;
+	int fd = fileno(fp_uboot);
+
+	if (fstat(fd, &st) == -1) {
+		printf("Error: Could not determine u-boot image size. %s\n",
+			strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	next_pbl_cmd = 0x82000000 - st.st_size;
+}
+
 static void generate_pbl_cmd(void)
 {
 	uint32_t val = next_pbl_cmd;
@@ -80,6 +97,7 @@
 /* load split u-boot with PBI command 81xxxxxx. */
 static void load_uboot(FILE *fp_uboot)
 {
+	init_next_pbl_cmd(fp_uboot);
 	while (next_pbl_cmd < 0x82000000) {
 		generate_pbl_cmd();
 		pbl_fget(64, fp_uboot);
diff --git a/tools/proftool.c b/tools/proftool.c
new file mode 100644
index 0000000..a48ed28
--- /dev/null
+++ b/tools/proftool.c
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2013 Google, 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
+ */
+
+/* Decode and dump U-Boot profiling information */
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+
+#include <compiler.h>
+#include <trace.h>
+
+#define MAX_LINE_LEN 500
+
+enum {
+	FUNCF_TRACE	= 1 << 0,	/* Include this function in trace */
+};
+
+struct func_info {
+	unsigned long offset;
+	const char *name;
+	unsigned long code_size;
+	unsigned long call_count;
+	unsigned flags;
+	/* the section this function is in */
+	struct objsection_info *objsection;
+};
+
+enum trace_line_type {
+	TRACE_LINE_INCLUDE,
+	TRACE_LINE_EXCLUDE,
+};
+
+struct trace_configline_info {
+	struct trace_configline_info *next;
+	enum trace_line_type type;
+	const char *name;	/* identifier name / wildcard */
+	regex_t regex;		/* Regex to use if name starts with / */
+};
+
+/* The contents of the trace config file */
+struct trace_configline_info *trace_config_head;
+
+struct func_info *func_list;
+int func_count;
+struct trace_call *call_list;
+int call_count;
+int verbose;	/* Verbosity level 0=none, 1=warn, 2=notice, 3=info, 4=debug */
+unsigned long text_offset;		/* text address of first function */
+
+static void outf(int level, const char *fmt, ...)
+		__attribute__ ((format (__printf__, 2, 3)));
+#define error(fmt, b...) outf(0, fmt, ##b)
+#define warn(fmt, b...) outf(1, fmt, ##b)
+#define notice(fmt, b...) outf(2, fmt, ##b)
+#define info(fmt, b...) outf(3, fmt, ##b)
+#define debug(fmt, b...) outf(4, fmt, ##b)
+
+
+static void outf(int level, const char *fmt, ...)
+{
+	if (verbose >= level) {
+		va_list args;
+
+		va_start(args, fmt);
+		vfprintf(stderr, fmt, args);
+		va_end(args);
+	}
+}
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Usage: proftool -cds -v3 <cmd> <profdata>\n"
+		"\n"
+		"Commands\n"
+		"   dump-ftrace\t\tDump out textual data in ftrace format\n"
+		"\n"
+		"Options:\n"
+		"   -m <map>\tSpecify Systen.map file\n"
+		"   -t <trace>\tSpecific trace data file (from U-Boot)\n"
+		"   -v <0-4>\tSpecify verbosity\n");
+	exit(EXIT_FAILURE);
+}
+
+static int h_cmp_offset(const void *v1, const void *v2)
+{
+	const struct func_info *f1 = v1, *f2 = v2;
+
+	return (f1->offset / FUNC_SITE_SIZE) - (f2->offset / FUNC_SITE_SIZE);
+}
+
+static int read_system_map(FILE *fin)
+{
+	unsigned long offset, start = 0;
+	struct func_info *func;
+	char buff[MAX_LINE_LEN];
+	char symtype;
+	char symname[MAX_LINE_LEN + 1];
+	int linenum;
+	int alloced;
+
+	for (linenum = 1, alloced = func_count = 0;; linenum++) {
+		int fields = 0;
+
+		if (fgets(buff, sizeof(buff), fin))
+			fields = sscanf(buff, "%lx %c %100s\n", &offset,
+				&symtype, symname);
+		if (fields == 2) {
+			continue;
+		} else if (feof(fin)) {
+			break;
+		} else if (fields < 2) {
+			error("Map file line %d: invalid format\n", linenum);
+			return 1;
+		}
+
+		/* Must be a text symbol */
+		symtype = tolower(symtype);
+		if (symtype != 't' && symtype != 'w')
+			continue;
+
+		if (func_count == alloced) {
+			alloced += 256;
+			func_list = realloc(func_list,
+					sizeof(struct func_info) * alloced);
+			assert(func_list);
+		}
+		if (!func_count)
+			start = offset;
+
+		func = &func_list[func_count++];
+		memset(func, '\0', sizeof(*func));
+		func->offset = offset - start;
+		func->name = strdup(symname);
+		func->flags = FUNCF_TRACE;	/* trace by default */
+
+		/* Update previous function's code size */
+		if (func_count > 1)
+			func[-1].code_size = func->offset - func[-1].offset;
+	}
+	notice("%d functions found in map file\n", func_count);
+	text_offset = start;
+	return 0;
+}
+
+static int read_data(FILE *fin, void *buff, int size)
+{
+	int err;
+
+	err = fread(buff, 1, size, fin);
+	if (!err)
+		return 1;
+	if (err != size) {
+		error("Cannot read profile file at pos %ld\n", ftell(fin));
+		return -1;
+	}
+	return 0;
+}
+
+static struct func_info *find_func_by_offset(uint32_t offset)
+{
+	struct func_info key, *found;
+
+	key.offset = offset;
+	found = bsearch(&key, func_list, func_count, sizeof(struct func_info),
+			h_cmp_offset);
+
+	return found;
+}
+
+/* This finds the function which contains the given offset */
+static struct func_info *find_caller_by_offset(uint32_t offset)
+{
+	int low;	/* least function that could be a match */
+	int high;	/* greated function that could be a match */
+	struct func_info key;
+
+	low = 0;
+	high = func_count - 1;
+	key.offset = offset;
+	while (high > low + 1) {
+		int mid = (low + high) / 2;
+		int result;
+
+		result = h_cmp_offset(&key, &func_list[mid]);
+		if (result > 0)
+			low = mid;
+		else if (result < 0)
+			high = mid;
+		else
+			return &func_list[mid];
+	}
+
+	return low >= 0 ? &func_list[low] : NULL;
+}
+
+static int read_calls(FILE *fin, int count)
+{
+	struct trace_call *call_data;
+	int i;
+
+	notice("call count: %d\n", count);
+	call_list = (struct trace_call *)calloc(count, sizeof(*call_data));
+	if (!call_list) {
+		error("Cannot allocate call_list\n");
+		return -1;
+	}
+	call_count = count;
+
+	call_data = call_list;
+	for (i = 0; i < count; i++, call_data++) {
+		if (read_data(fin, call_data, sizeof(*call_data)))
+			return 1;
+	}
+	return 0;
+}
+
+static int read_profile(FILE *fin, int *not_found)
+{
+	struct trace_output_hdr hdr;
+
+	*not_found = 0;
+	while (!feof(fin)) {
+		int err;
+
+		err = read_data(fin, &hdr, sizeof(hdr));
+		if (err == 1)
+			break; /* EOF */
+		else if (err)
+			return 1;
+
+		switch (hdr.type) {
+		case TRACE_CHUNK_FUNCS:
+			/* Ignored at present */
+			break;
+
+		case TRACE_CHUNK_CALLS:
+			if (read_calls(fin, hdr.rec_count))
+				return 1;
+			break;
+		}
+	}
+	return 0;
+}
+
+static int read_map_file(const char *fname)
+{
+	FILE *fmap;
+	int err = 0;
+
+	fmap = fopen(fname, "r");
+	if (!fmap) {
+		error("Cannot open map file '%s'\n", fname);
+		return 1;
+	}
+	if (fmap) {
+		err = read_system_map(fmap);
+		fclose(fmap);
+	}
+	return err;
+}
+
+static int read_profile_file(const char *fname)
+{
+	int not_found = INT_MAX;
+	FILE *fprof;
+	int err;
+
+	fprof = fopen(fname, "rb");
+	if (!fprof) {
+		error("Cannot open profile data file '%s'\n",
+		      fname);
+		return 1;
+	} else {
+		err = read_profile(fprof, &not_found);
+		fclose(fprof);
+		if (err)
+			return err;
+
+		if (not_found) {
+			warn("%d profile functions could not be found in the map file - are you sure that your profile data and map file correspond?\n",
+			     not_found);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int regex_report_error(regex_t *regex, int err, const char *op,
+			      const char *name)
+{
+	char buf[200];
+
+	regerror(err, regex, buf, sizeof(buf));
+	error("Regex error '%s' in %s '%s'\n", buf, op, name);
+	return -1;
+}
+
+static void check_trace_config_line(struct trace_configline_info *item)
+{
+	struct func_info *func, *end;
+	int err;
+
+	debug("Checking trace config line '%s'\n", item->name);
+	for (func = func_list, end = func + func_count; func < end; func++) {
+		err = regexec(&item->regex, func->name, 0, NULL, 0);
+		debug("   - regex '%s', string '%s': %d\n", item->name,
+		      func->name, err);
+		if (err == REG_NOMATCH)
+			continue;
+
+		if (err != REG_NOERROR) {
+			regex_report_error(&item->regex, err, "match",
+					   item->name);
+			break;
+		}
+
+		/* It matches, so perform the action */
+		switch (item->type) {
+		case TRACE_LINE_INCLUDE:
+			info("      include %s at %lx\n", func->name,
+			     text_offset + func->offset);
+			func->flags |= FUNCF_TRACE;
+			break;
+
+		case TRACE_LINE_EXCLUDE:
+			info("      exclude %s at %lx\n", func->name,
+			     text_offset + func->offset);
+			func->flags &= ~FUNCF_TRACE;
+			break;
+		}
+	}
+}
+
+static void check_trace_config(void)
+{
+	struct trace_configline_info *line;
+
+	for (line = trace_config_head; line; line = line->next)
+		check_trace_config_line(line);
+}
+
+/**
+ * Check the functions to see if they each have an objsection. If not, then
+ * the linker must have eliminated them.
+ */
+static void check_functions(void)
+{
+	struct func_info *func, *end;
+	unsigned long removed_code_size = 0;
+	int not_found = 0;
+
+	/* Look for missing functions */
+	for (func = func_list, end = func + func_count; func < end; func++) {
+		if (!func->objsection) {
+			removed_code_size += func->code_size;
+			not_found++;
+		}
+	}
+
+	/* Figure out what functions we want to trace */
+	check_trace_config();
+
+	warn("%d functions removed by linker, %ld code size\n",
+	     not_found, removed_code_size);
+}
+
+static int read_trace_config(FILE *fin)
+{
+	char buff[200];
+	int linenum = 0;
+	struct trace_configline_info **tailp = &trace_config_head;
+
+	while (fgets(buff, sizeof(buff), fin)) {
+		int len = strlen(buff);
+		struct trace_configline_info *line;
+		char *saveptr;
+		char *s, *tok;
+		int err;
+
+		linenum++;
+		if (len && buff[len - 1] == '\n')
+			buff[len - 1] = '\0';
+
+		/* skip blank lines and comments */
+		for (s = buff; *s == ' ' || *s == '\t'; s++)
+			;
+		if (!*s || *s == '#')
+			continue;
+
+		line = (struct trace_configline_info *)calloc(1,
+							      sizeof(*line));
+		if (!line) {
+			error("Cannot allocate config line\n");
+			return -1;
+		}
+
+		tok = strtok_r(s, " \t", &saveptr);
+		if (!tok) {
+			error("Invalid trace config data on line %d\n",
+			      linenum);
+			return -1;
+		}
+		if (0 == strcmp(tok, "include-func")) {
+			line->type = TRACE_LINE_INCLUDE;
+		} else if (0 == strcmp(tok, "exclude-func")) {
+			line->type = TRACE_LINE_EXCLUDE;
+		} else {
+			error("Unknown command in trace config data line %d\n",
+			      linenum);
+			return -1;
+		}
+
+		tok = strtok_r(NULL, " \t", &saveptr);
+		if (!tok) {
+			error("Missing pattern in trace config data line %d\n",
+			      linenum);
+			return -1;
+		}
+
+		err = regcomp(&line->regex, tok, REG_NOSUB);
+		if (err) {
+			free(line);
+			return regex_report_error(&line->regex, err, "compile",
+						  tok);
+		}
+
+		/* link this new one to the end of the list */
+		line->name = strdup(tok);
+		line->next = NULL;
+		*tailp = line;
+		tailp = &line->next;
+	}
+
+	if (!feof(fin)) {
+		error("Cannot read from trace config file at position %ld\n",
+		      ftell(fin));
+		return -1;
+	}
+	return 0;
+}
+
+static int read_trace_config_file(const char *fname)
+{
+	FILE *fin;
+	int err;
+
+	fin = fopen(fname, "r");
+	if (!fin) {
+		error("Cannot open trace_config file '%s'\n", fname);
+		return -1;
+	}
+	err = read_trace_config(fin);
+	fclose(fin);
+	return err;
+}
+
+static void out_func(ulong func_offset, int is_caller, const char *suffix)
+{
+	struct func_info *func;
+
+	func = (is_caller ? find_caller_by_offset : find_func_by_offset)
+		(func_offset);
+
+	if (func)
+		printf("%s%s", func->name, suffix);
+	else
+		printf("%lx%s", func_offset, suffix);
+}
+
+/*
+ * # tracer: function
+ * #
+ * #           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+ * #              | |      |          |         |
+ * #           bash-4251  [01] 10152.583854: path_put <-path_walk
+ * #           bash-4251  [01] 10152.583855: dput <-path_put
+ * #           bash-4251  [01] 10152.583855: _atomic_dec_and_lock <-dput
+ */
+static int make_ftrace(void)
+{
+	struct trace_call *call;
+	int missing_count = 0, skip_count = 0;
+	int i;
+
+	printf("# tracer: ftrace\n"
+		"#\n"
+		"#           TASK-PID   CPU#    TIMESTAMP  FUNCTION\n"
+		"#              | |      |          |         |\n");
+	for (i = 0, call = call_list; i < call_count; i++, call++) {
+		struct func_info *func = find_func_by_offset(call->func);
+		ulong time = call->flags & FUNCF_TIMESTAMP_MASK;
+
+		if (TRACE_CALL_TYPE(call) != FUNCF_ENTRY &&
+		    TRACE_CALL_TYPE(call) != FUNCF_EXIT)
+			continue;
+		if (!func) {
+			warn("Cannot find function at %lx\n",
+			     text_offset + call->func);
+			missing_count++;
+			continue;
+		}
+
+		if (!(func->flags & FUNCF_TRACE)) {
+			debug("Funcion '%s' is excluded from trace\n",
+			      func->name);
+			skip_count++;
+			continue;
+		}
+
+		printf("%16s-%-5d [01] %lu.%06lu: ", "uboot", 1,
+		       time / 1000000, time % 1000000);
+
+		out_func(call->func, 0, " <- ");
+		out_func(call->caller, 1, "\n");
+	}
+	info("ftrace: %d functions not found, %d excluded\n", missing_count,
+	     skip_count);
+
+	return 0;
+}
+
+static int prof_tool(int argc, char * const argv[],
+		     const char *prof_fname, const char *map_fname,
+		     const char *trace_config_fname)
+{
+	int err = 0;
+
+	if (read_map_file(map_fname))
+		return -1;
+	if (prof_fname && read_profile_file(prof_fname))
+		return -1;
+	if (trace_config_fname && read_trace_config_file(trace_config_fname))
+		return -1;
+
+	check_functions();
+
+	for (; argc; argc--, argv++) {
+		const char *cmd = *argv;
+
+		if (0 == strcmp(cmd, "dump-ftrace"))
+			err = make_ftrace();
+		else
+			warn("Unknown command '%s'\n", cmd);
+	}
+
+	return err;
+}
+
+int main(int argc, char *argv[])
+{
+	const char *map_fname = "System.map";
+	const char *prof_fname = NULL;
+	const char *trace_config_fname = NULL;
+	int opt;
+
+	verbose = 2;
+	while ((opt = getopt(argc, argv, "m:p:t:v:")) != -1) {
+		switch (opt) {
+		case 'm':
+			map_fname = optarg;
+			break;
+
+		case 'p':
+			prof_fname = optarg;
+			break;
+
+		case 't':
+			trace_config_fname = optarg;
+			break;
+
+		case 'v':
+			verbose = atoi(optarg);
+			break;
+
+		default:
+			usage();
+		}
+	}
+	argc -= optind; argv += optind;
+	if (argc < 1)
+		usage();
+
+	debug("Debug enabled\n");
+	return prof_tool(argc, argv, prof_fname, map_fname,
+			 trace_config_fname);
+}